Convert C# statements including NSubstitute code to VB.net - c#

While reading the NSubstitute tutorial i convert the samples written in C# to VB.net to understand the functionality, but I need your support for these (unrelated) statements, which I can't convert despite all the care taken:
1.
calculator().Received().Add(1, Arg.Is(Of Integer)(function(x) new[] {-2,-5,-10}.Contains(x)))
2.
Note: foo is a derived object from an interface with a void method called "SayHello"
foo.When(x >= x.SayHello("World")).Do(x => counter++);
3.
calculator().When(x >= x.Add(-2, -2)).Do(x => { throw new Exception(); });
Note: engine is a derived object from this interface:
public interface IEngine {
event EventHandler Idling;
event EventHandler<LowFuelWarningEventArgs> LowFuelWarning;
event Action<int> RevvedAt;
}
4.
engine.Idling += (sender, args) => wasCalled = true;
5.
engine.Idling += Raise.EventWith(new object(), new EventArgs());
6.
engine.RevvedAt += rpm => revvedAt = rpm;
With your support I hope, I'm able to convert the remaining statements on my own.
Thank you in advance
Michael

It seems you want to convert Lambda's and adding event handlers.
Lambda from c#
.Where(x => x.Foo = 1)
.Do(x => x.Bar())
translates into
.Where(function(x) x.Foo = 1)
.Do(sub(x) x.Bar())
In VB.Net you have to take into account if the Labda is actually performing a function or a sub and code it accordingly.
Adding events in c#
engine.Idling += MyEventHandler
in VB.Net
AddHandler engine.Idling, AddressOf MyEventHandler
VB.Net lets u add the event like this. Removing an event is done by the keyword RemoveHandler

To add to Jeroen's answer, the general format for adding an event handler is:
AddHandler someObject.SomeEvent, SomeDelegate
You can use the AddressOf operator to create a delegate that refers to a named method but that is not the only way. A Lambda also creates a delegate so this:
engine.Idling += (sender, args) => wasCalled = true;
becomes this:
AddHandler engine.Idling, Sub(sender, args) wasCalled = True
Also, this line is not actually adding an event handler:
engine.RevvedAt += rpm => revvedAt = rpm;
so AddHandler won't work. I have never done it myself but I believe that you need to call Delegate.Combine for that:
engine.RevvedAt = [Delegate].Combine(engine.RevvedAt, Sub(rpm) revvedAt = rpm)

Related

How to correctly reset a custom event in C#?

I have this code:
private void loadGENIOFileToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog dlgFile = new OpenFileDialog();
dlgFile.InitialDirectory = Properties.Settings.Default.PreviousPath;
dlgFile.Title = "Select GENIO file";
dlgFile.Filter = "GENIO files (*.txt)|*.txt";
dlgFile.FilterIndex = 0;
dlgFile.Multiselect = false;
if (dlgFile.ShowDialog() == DialogResult.OK)
{
Properties.Settings.Default.PreviousPath = Path.GetDirectoryName(dlgFile.FileName);
DeleteView();
m_oThreadServices.OnLoadingCompleted += (_sender, _e) =>
{
mruMenu.AddFile(dlgFile.FileName);
m_sUITInfo.dbDatabase = m_oThreadServices.GetDatabase();
CreateView();
};
m_oThreadServices.SetGenioFilePath(dlgFile.FileName);
m_oThreadServices.start();
}
}
But I am also trying to implement a MRU handler:
private void OnMruFile(int number, String filename)
{
if (File.Exists(filename))
{
Properties.Settings.Default.PreviousPath = Path.GetDirectoryName(filename);
DeleteView();
m_oThreadServices.OnLoadingCompleted += (_sender, _e) =>
{
mruMenu.SetFirstFile(number);
m_sUITInfo.dbDatabase = m_oThreadServices.GetDatabase();
CreateView();
};
m_oThreadServices.SetGenioFilePath(filename);
m_oThreadServices.start();
}
else
mruMenu.RemoveFile(number);
}
}
My m_oThreadServices.OnLoadingCompleted line of code seems to require that I use += and as a result, if I first load a file, it adds the first event handler. If I then go to use the MRU list to load a different file it ends up running two OnLoadingCompleted handlers.
I tried m_oThreadServices.OnLoadingCompleted = but it will not allow it. So what is the right way for me to intercept the event handler and not end up calling both sets of code? Am I going about it wrong?
Thank you.
You should make sure your event handlers are unsubscribed from the event source once the event is raised.
In order to do that, you have to modify a bit the anonymous handlers. For instance, this snippet:
m_oThreadServices.OnLoadingCompleted += (_sender, _e) =>
{
mruMenu.AddFile(dlgFile.FileName);
m_sUITInfo.dbDatabase = m_oThreadServices.GetDatabase();
CreateView();
};
should be like this:
EventHandler onLoadingCompleted = null;
onLoadingCompleted = (_sender, _e) =>
{
m_oThreadServices.OnLoadingCompleted -= onLoadingCompleted;
mruMenu.AddFile(dlgFile.FileName);
m_sUITInfo.dbDatabase = m_oThreadServices.GetDatabase();
CreateView();
};
m_oThreadServices.OnLoadingCompleted += onLoadingCompleted;
Same for the other.
The line
EventHandler onLoadingCompleted = null;
is needed to avoid using uninitialized variable compiler error here
m_oThreadServices.OnLoadingCompleted -= onLoadingCompleted;
You can remove a handler if it's a named function:
private void OnLoadingComplete_AddFile(_sender, _e)
{
mruMenu.AddFile(dlgFile.FileName);
m_sUITInfo.dbDatabase = m_oThreadServices.GetDatabase();
CreateView();
}
...
m_oThreadServices.OnLoadingCompleted += OnLoadingComplete_AddFile;
...
m_oThreadServices.OnLoadingCompleted -= OnLoadingComplete_AddFile;
Removing a handler that hasn't been added (or has already been removed) is a no-op, so you can just remove the "other" handler before you add one: this will ensure there is at most one handler.
So basically += is syntactic sugar for calling Combine on your event. Delegates are stored in an Invocation List, and the default behavior when an event is fired is for each delegate in the invocation list to get called in the order they were added. This is why you cannot simply set OnLoadingCompleted to one delegate with an = sign - an event stores a list of delegates, not one.
You could remove a delegate with -= (syntactic sugar for calling Remove). Perhaps you want to formally declare the previous delegate somewhere rather than passing it as a lambda. This would let you remove it when you are done with it.
There is no straightforward way of removing anonymous or unknown events from a handler. However, you can take a look at this forum posting on MSDN: https://social.msdn.microsoft.com/Forums/vstudio/en-US/45071852-3a61-4181-9a25-068a8698b8b6/how-do-i-determine-if-an-event-has-a-handler-already?forum=netfxbcl
There is some code and discussion about using reflection to remove delegates from your event handler.
It might be better though to understand exactly what you are wanting to accomplish. Perhaps there is a better way to get the end-result that you are looking for rather than rewire events.
It isn't usually good practice to remove established event code to change the behavior of the code you want to implement. It can lead to unintended consequences, and erratic behavior. If event code is defined, it is almost always best to keep it in place and design your application around it.
On the other hand, if this is code that is added by you, or in your code-base, you can remove it, if you have done the proper research to validate its removal and not cause the application to break elsewhere. The best way to do that would be to have the event code in a named function:
public void MyEventCode(object sender, EventArgs args)
{
// Do event stuff..
}
Then you can remove the event by name:
control.DoMyEvent -= MyEventCode;

Convert event without EventArgs using Observable.FromEvent

I'm struggling with converting the following event to an IObservable:
public delegate void _dispSolutionEvents_OpenedEventHandler();
event _dispSolutionEvents_OpenedEventHandler Opened;
The event comes from a library so I can't change it.
The overload of IObservable.FromEvent that should do it has the following signature:
public static IObservable<Unit> FromEvent
( Action<Action> addHandler
, Action<Action> removeHandler
)
So I tried converting the event like this:
var opened = Observable.FromEvent
( h => _SolutionEvents.Opened += h
, h => _SolutionEvents.Opened -= h
);
But the compiler doesn't like _SolutionEvents.Opened += h and _SolutionEvents.Opened += h because
Cannot implicitly convert type 'System.Action' to 'EnvDTE._dispSolutionEvents_OpenedEventHandler'.
I don't think that I can just say_SolutionEvents.Opened += new _dispSolutionEvents_OpenedEventHandler(h) because then removal won't work because I have a different instance, right?
There is another overload of Observable.FromEvent with the following signature:
public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>
( Func<Action<TEventArgs>, TDelegate> conversion
, Action<TDelegate> addHandler
, Action<TDelegate> removeHandler
)
This one allows to convert the action to an event handler, but it seems to only work with TEventArgs.
Is Rx missing an appropriate overload or am I missing something?
This turns out that it is very easy to use the FromEvent pattern.
Just do this:
var opened = Observable.FromEvent<_dispSolutionEvents_OpenedEventHandler, Unit>(
h => () => h(Unit.Default),
h => _SolutionEvents.Opened += h,
h => _SolutionEvents.Opened -= h);
I've tested the observable with this code:
void Main()
{
var _SolutionEvents = new Foo();
var opened = Observable.FromEvent<_dispSolutionEvents_OpenedEventHandler, Unit>(h => () => h(Unit.Default), h => _SolutionEvents.Opened += h, h => _SolutionEvents.Opened -= h);
opened.Subscribe(x => Console.WriteLine("Opened"));
_SolutionEvents.OnOpened();
}
public delegate void _dispSolutionEvents_OpenedEventHandler();
public class Foo
{
public event _dispSolutionEvents_OpenedEventHandler Opened;
public void OnOpened()
{
this.Opened?.Invoke();
}
}
It produces the following expected output:
Opened
It's worth noting that there is no IObservable interface, but only an IObservable<T> so you must return something. The trick here is to convert delegate void _dispSolutionEvents_OpenedEventHandler() into an IObservable<Unit> to make it work and that's what the h => () => h(Unit.Default) does.
You are running into a a type issue here. The _dispSolutionEvents_OpenedEventHandler type is not Action. It looks like the Action type, but it is not the Action type.
IMO this event does not conform to the .NET standards for events. Generally the delegate would match the pattern of taking a sender object parameter and an EventArg subclass of for the second parameter.
ie.
public delegate void _dispSolutionEvents_OpenedEventHandler(object sender, EventArgs e);
If you try to just attach an Action to the event you will find that fails too.
Action onOpened = ()=>Console.WriteLine("Opened");
_SolutionEvents.Opened += onOpened; //CS0029 Cannot implicitly convert type 'System.Action' to '_dispSolutionEvents_OpenedEventHandler'
The compiler is smart enough to do some type inference if you do this;
_SolutionEvents.Opened+= () => Console.WriteLine("Opened");
but when you are using Rx, you are already typed into the Action type, so are effectively back at the previous issue above.
If the library owner was nice, the event would follow the normal sender/eventArgs pattern. Failing that, they would at least specify the delegate as just an Action instead of their own customer parameterless, void method. :-/
So, as the event you have doesn't meet the standard .NET patterns, you will need to provide Rx some more hand-holding (blame your library provider not Rx).
You could fight the FromEvent/FromEventPattern methods, but as your library is not in the spirit of an Event, I would suggest just going with the simple use of Observable.Create which at least keeps the code obvious what is happening and should allow the next user to better understand it.
Observable.Create<Unit>(obs =>
{
_dispSolutionEvents_OpenedEventHandler handler = () => obs.OnNext(Unit.Default);
_SolutionEvents.Opened += handler;
return System.Reactive.Disposables.Disposable.Create(() => _SolutionEvents.Opened -= handler);
});

Can someone explain this line of code to me please for treeview in Visual Studio?

TreeList1.FocusedNodeChanged += treeList1_FocusedNodeChanged;
Specifically what does the += do?
It is used to assign event handlers to events.
From MSDN:
The += operator is also used to specify a method that will be called in response to an event; such methods are called event handlers. The use of the += operator in this context is referred to as subscribing to an event. For more information, see How to: Subscribe to and Unsubscribe from Events (C# Programming Guide). and Delegates (C# Programming Guide).
In your case, it assigns the treeList1_FocusedNodeChanged handler to the FocusedNodeChanged event of TreeList1.
Additional Info:
The function of the += operator depends on the context. While in your case it is used to subscribe to an event, in other cases, it may be used for addition assignment.
Say for example, this code:
int x = 5;
x += 6; // This basically translates to x = x + 5, thus assigning x a value of 11.
Also, you can use lambda expressions instead of a separate method while subscribing to events:
TreeList1.FocusedNodeChanged += (s, e) => { // ... // };
The code in place of // ... // would be whatever there was in the separate event handler.

what is += (o, arg) => actually achieving?

Sorry to ask all, but I'm an old hand Vb.net guy who's transferring to c#. I have the following piece of code that seems to activate when the (in this case) postAsync method is fired. I just don;t understand what the code is doing (as follows):-
app.PostCompleted +=
(o, args) =>
{
if (args.Error == null)
{
MessageBox.Show("Picture posted to wall successfully.");
}
else
{
MessageBox.Show(args.Error.Message);
}
};
if anyone could explain what the += (o,args) => is actually acheiving I'd be so greatful....
many thanks in advance.
Tim
(o,args) => defines a lambda expression that takes two parameters named o and args. The types of those parameters is inferred according to the type of PostCompleted (if PostCompleted is an EventHandler, then they will be respectively of type Object and EventArgs). The expression's body then follows after the =>.
The result is than added as an handler to PostCompleted.
As such, it's a less verbose way to write:
app.PostCompleted += delegate(object o, EventArgs args)
{
// ...
};
Which is a shorthand for:
void YourHandler(object o, EventArgs args)
{
// ...
}
// ...
app.PostCompleted += YourHandler;
That is an added handler for the PostCompleted event using a lambda expression. It is similar to
app.PostCompleted += MyHandler;
// ...
private void MyHandler(object sender, EventArgs e) {
// ...
}
But when using lambda expressions, you can't detach the handler easily.
It's shorthand for a delegate defining the event handler for the POST completion event:
app.PostCompleted += delegate(object o, EventArgs args) {
// ...
};
See also Anonymous Methods.
Assuming PostCompleted is an event, you are basically creating an event handler using lambda notation.
This code snipped is equivalent to:
app.PostCompleted += delegate (o, args)
{
if (args.Error == null)
{
MessageBox.Show("Picture posted to wall successfully.");
}
else
{
MessageBox.Show(args.Error.Message);
}
};
The vb.net equivalent would look like this:
AddHandler app.PostCompleted, Function(o, args)
''# ...
End Function
Note that this requires Visual Studio 2010/.Net 4, but the C# code works back in Visual Studio 2008/.Net 3.5.
But that's only partly true. In C#, this is a way to define a method as an event handler in one place. In VB.Net, you can use the Handles keyword, and so the actual equivalent might look more like this:
Public Sub App_PostCompleted(ByVal Sender as Object, ByVall e As EventArgs) Handles app.PostCompleted
''#
End Sub
But even that's not completely equivalent, since you gave the method a name and can call it from anywhere. The only reference to the C# code (and thus the only way to call it) is through the event subscription.
The (o,args) => part is a lambda expression, which is an anonymous function.
the += part assigns the lambda expression to be called when the event fires.

How to remove the event?

For Sample ....
SampleClass :
public class SampleClass
{
public delegate void BeforeEditorHandle();
public event BeforeEditorHandle OnBeforeEditor;
}
MainMethod
static void Main(string[] args)
{
SampleClass sc = new SampleClass();
// Add Event
sc.OnBeforeEditor +=new SampleClass.BeforeEditorHandle(sc_OnBeforeEditor);
// Remove Event
sc.OnBeforeEditor -= new SampleClass.BeforeEditorHandle(sc_OnBeforeEditor);
}
And , if I add the event by dynamic like this ...↓
sc.OnBeforeEditor += () => { };
Should I remove the event like ↓
sc.OnBeforeEditor -= () => { };
But I think this is very ugly when I have too much sources in the event....
Can anybody tell me the best way to remove the event please ?
You can assign the event handler/lambda to a variable which you can then subscribe and unsubscribe:
var myHandler = () => { };
sc.OnBeforeEditor += myHandler;
sc.OnBeforeEditor -= myHandler;
I'm pretty sure your code here won't work:
And , if I add the event by dynamic like this ...↓
sc.OnBeforeEditor += () => { };
Should I remove the event like ↓
sc.OnBeforeEditor -= () => { };
This is because restating the lambda creates a new different lambda.
You need to store the old reference and use it to unsubscribe:
BeforeEditorHandle myHandler=() => { }
sc.OnBeforeEditor += myHandler;
...
sc.OnBeforeEditor -= myHandler;
For easier unsubscribing you can collect your event handlers in a collection (For example List<BeforeEditorHandle>).
From MSDN:
It is important to notice that you
cannot easily unsubscribe from an
event if you used an anonymous
function to subscribe to it. To
unsubscribe in this scenario, it is
necessary to go back to the code where
you subscribe to the event, store the
anonymous method in a delegate
variable, and then add the delegate to
the event. In general, we recommend
that you do not use anonymous
functions to subscribe to events if
you will have to unsubscribe from the
event at some later point in your
code. For more information about
anonymous functions, see Anonymous
Functions (C# Programming Guide).

Categories