C++ Pointers in C# MVVM - c#

Currently, I am working on a project in C# which use C++ libraries. To use the C++ libraries they are wrapped in CLR. Communication between the C++ and C# are in both ways.
I have the following problem. At a point the C++ calls some functions in CLR which will raise events with objects that have C++ raw pointers.
For example:
C++ object
class CObject {
private:
char* ptr;
}
CLR object
ref class CLRObject {
public: CLRObject(CObject* p) : m_native(p) {}
private: CObject* m_native;
}
C# object
class CSHObject : CLRObject {
}
Now because CSHObject is send as an argument to the event to multiple handlers they will all get a reference to the same object. So when one of the event handlers will modify the object which is pass by the event, the other listeners of the event will get the modified object.
For example:
C++ creates the object:
void updateListeners() {
updateListener(new CObject());
}
CLR overwrites the updateListener:
void updateListener(CObject* obj) {
m_wrapper->updateListener(gcnew CLRObject(obj))
}
C# will raise the event:
public event EventHandler<MyEventArgs> MyEvent;
void updateListener(CLRObject obj) {
MyEvent?.Invoke(this, new MyEventArgs(new CSHObject(obj)));
}
Now my question, how we should handle these events? from the point of MVVM view. Because the CLRObject is the Model in this case, but the same model is shared between multiple view models. Which I think is not the correct way of the MVVM.
So:
should all the event listeners create their own Models and copy the required information from the CLRObject?
each event listener create a deep copy of the object?
the current implementation is the correct way and I should not change.
Obs:
I don't have good knowledge in C#, CLR.
All the example code is made up, because the real code is too long and contains a lot of other things.

Related

Is there a way to implement INotifyPropertyChanged on objects that are interop marshalled without affecting binary layout?

I've been marshalling objects in C# (read from a binary file stream) that are written from unmanaged C++ structs using C#'s COM interop functionalities. My goal is to make these objects available to data binding by implementing the INotifyPropertyChanged interface.
The problem is, that implementing INotifyPropertyChanged inevitably comes with exposing a property changed event as public class member. This is recognized and treated as 4-byte structure member by the marshalling services, thus changing the binary layout during marshalling operations.
This is a simplistic demonstration of the issue. Consider this C++ struct:
struct Struct
{
int SomeMember; // example member
}
and this C# class adaption of the struct:
[StructLayout(LayoutKind.Sequential)] // required for class marshalling
public class CppStruct
{
private int someMember; // encapsuled properties are recognized during marshalling
public int SomeMember { get => someMember; set => someMember = value; } // example member
}
and this same class with the implemented INotifyPropertyChanged interface:
[StructLayout(LayoutKind.Sequential)] // required for class marshalling
public class CppStructNotifyPropertyChanged : INotifyPropertyChanged
{
private int someMember; // encapsuled properties are recognized during marshalling
public int SomeMember
{
get => someMember;
set
{
someMember = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SomeMember)));
}
}
public event PropertyChangedEventHandler PropertyChanged; // required by INotifyPropertyChanged implementation
}
Then System.Runtime.InteropServices.Marshal.SizeOf< CppStruct >() gives 4, which is the correct size of the binary layout of this structure, but System.Runtime.InteropServices.Marshal.SizeOf<CppStructNotifyPropertyChanged>() gives 8. This shows that the PropertyChanged member is automatically treated as 4-byte type.
I've tried finding a way to hide the event member to marshaling but this just doesn't seem to be possible. Any sort of inheritance related solution to this seem inapplicable as for INotifyPropertyChanged events to cover all members, they need to be invoked on all (including base class') members at assignment time. I've also thought of writing a custom serializer for the class, that would ignore the event member or introduce custom attributes that allow hiding of members, but that's a worst-case option for me. I would like to keep using the default marshalling functionalities if at all possible.
Is there any way to achieve this?
It might be worth to mention, I have no access nor control over the C++ side writing and reading these structures and I don't see a reason for that either. Having the event object in any form on the file is of no use. Also I'm using .NET Framework 4.7.2 with Visual Studio 2017.

How to call VRInput Class Events (OnClick, OnDoubleClick, ...) from another Class?

I'm adding a replaying feature to my game. Having this feature, I can capture user's input to the game and feed them back to Unity later on for replaying the game. But the design of VRStandardAssets.Utils.VRInput class prevents me to mimic user inputs.
This class does not provide any public method to make it possible to trigger its events (e.g. OnClick or OnDoubleClick events) programmatically. So I decided to create a derived class from it and write my own public methods to trigger the events. This strategy failed because VRInput's methods are private meaning that I cannot invoke them from a derived class.
It is recommended for this type of classes to provide a protected virtual void On[eventName](subclassOfEventArgs e) method to provide a way for a derived class to handle the event using an override but this class does not have it (why so restrictive?). I guess it's a poor design from Unity. This poor design also makes it hard to write unit/integration tests.
Am I missing something here? Can I still do something to trick other classes to think they are dealing with VRInput class while replaying the game?
In fact you can trigger theses events (OnClick, OnDoubleClick or any other events) from another class and without using reflection using this clever hack (Inspired by this article):
C# is not really type safe so you can share the same memory location. First declare a class with two fields that share the same memory space:
[StructLayout(LayoutKind.Explicit)]
public class OverlapEvents
{
[FieldOffset(0)]
public VRInput Source;
[FieldOffset(0)]
public EventCapture Target;
}
Then you can declare a new class that will intercept and call the other event:
public class EventCapture
{
public event Action OnClick;
public void SimulateClick()
{
InvokeClicked();
}
// This method will call the event from VRInput!
private void InvokeClicked()
{
var handler = OnClick;
if (handler != null)
handler();
}
}
Then finally register it and call it:
public static void Main()
{
input = GetComponent<VRInput>();
// Overlap the event
var o = new OverlapEvents { Source = input };
// You can now call the event! (Note how Target should be null but is of type VRInput)
o.Target.SimulateClick();
}
Here is a simple dotNetFiddle that show it working (at least outside of unity)
It is recommended for this type of classes to provide a protected virtual void On[eventName](subclassOfEventArgs e) method to provide a way for a derived class to handle the event using an override but this class does not have it (why so restrictive?). I guess it's a poor design from Unity. This poor design also makes it hard to write unit/integration tests.
All code is good code. All code is also bad code. Depends on your evaluation criteria. Unity's developers probably didn't think about your use case. As another conflicting rule of thumb, software should also be as simple & rigid as possible, so anticipating subclassing without a known use case might be considered overengineering.
As for how you can work around this, see How do I raise an event via reflection in .NET/C#?

Marshaling a Struct with methods using C# P/Invoke

I'm trying to PInvoke into this C++ library function:
int Initialize(Callback* callback);
struct Callback
{
//.......
void virtual StateChanged(int state) = 0;
};
I have tried this naive C# code, but it doesn't work.
[DllImport("CPlusPlusLibrary.dll", SetLastError = true, EntryPoint = "?Initialize#CPlusPlusLibrary##YAHPAUCallback#1##Z")]
public static extern int Initialize(Callback callback);
[StructLayout(LayoutKind.Sequential)]
public class Callback
{
//....
public delegate void IntDelegate(int state);
public IntDelegate StateChanged(int state);
}
var callback = new Callback();
var result = Initialize(callback);
It is impossible to do it that way as far as I know. Methods are not "in there" as fields would be, beside this, creating a struct with virtual method will create a vtable pointer in your objects, that you are not taking into account in c# mirrored class.
What you can do is to PInvoke to method that takes a functionPointer (in C++) and pass a delegate (C#) there. You can then use this function pointer to call it from native code and your delegate will launch.
You could then change your stateChange method definition to take a Callback* as a first parameter, so when you call it from native code you can pass an object pointer which is responsible of that change and marshal it back to Callback in c#.
//Edit without having source of native dll, building a bridge between c# and c++ is what comes to my mind. This can be done with c++/cli or c++, sticking to native my idea would be something like this:
//c++ <--> new c++ dll <--> c#
struct CallbackBridge : public Callback
{
void (*_stateChanged)(int);
virtual void stateChanged(int state)
{
if (_stateChanged)
_stateChanged(this, state);
}
};
void* CreateCallback() { return new CallbackBridge(); }
void DeleteCallback(void* callback); { delete callback; }
void setStateChanged(void* callback, void (*ptr)(void*, int))
{
CallbackBridge* bridge = (CallbackBridge*)callback;
bridge->stateChanged = ptr;
}
///... other helper methods
The idea here is to treat your object as a black box (hence void* everywhere - it can be any pointer, but from c# you will just see this a a SafeHandle / IntPtr and write helper methods that you can PInvoke to to create / delete and modify objects. You can mock those virtual calls by giving your object a delegate through such method.
From c# usage could look like this: (IntPtr for simplicity, SafeHandle could be used):
IntPtr callback = CreateCallback();
SetStateChanged(callback, myCallback);
//somewhere later:
DeleteCallback(callback);
void MyCallback(IntrPtr callback, int state)
{
int someData = SomeOtherHelperMethod(callback);
ConsoleWrite("SomeData of callback is {0} and it has changed it's state to {1}", someData, state);
}
I know, it's a bit clumsy for bigger objects, but without c++/cli wrapper I have never found any better way to be able to handle all those tricky cases like virtual calls etc.
Your C# class is no substitute for the C++ struct, it has an entirely different internal organization. The C++ struct has a v-table because of the virtual method. It is not a POD type anymore. It has a hidden field that contains a pointer to the v-table. And a compiler-generated constructor and destructor. The v-table is an array of pointers to the virtual methods. A C# class has something similar, called "method table", but it organized completely differently. It will have the System.Object methods for example and contains pointers to all methods, not just the virtual ones. The class object layout is completely different as well. The struct keyword in the C++ language in this context is just a substitute for the class keyword with all members public by default.
A wrapper class written in the C++/CLI language is required. There's a bit of a learning curve to the language but it is not steep if you've got experience with .NET and C++. Boilerplate code for such a wrapper is in this answer. You can call back from native code into managed code through a function pointer returned by Marshal::GetFunctionPointerForDelegate().
I have heard that you don't have the source code of C++ library. Then you might have a look at this.
But exporting classes from unmanaged dll to managed one without source sounds dangerous to me.

How Callback functions are useful while building and DLL

Are callback functions equivelent to events in C#(.NET).
What I understand about callback function is, it is a function that is called by a reference to that Function.
Example Code will be:
void cbfunc()
{
printf("called");
}
int main ()
{
void (*callback)(void);
callback=(void *)cbfunc;
callback();
return 0;
}
Now What I dont understand is How is this use full with respect to notifying from the DLL to client.
Suppose I want to do /perform some method1() when I recieve Data on my DLL method2().
Any comparasion with Events in .NET will be helpfull in a great way.
Callbacks and interface classes are great ways to manage your code boundaries. They help create formal boundaries and/or layers in your code instead of lumping everything together. This becomes necessary when working on large software solutions.
Below is an example of how to use callbacks and interface classes. In the library/dll code the only thing that should be exposed to the main executable is the myddl_interface class and the function getMyDllInterface(). Using an interface class like this completely hides the implementation detail from the main executable. The interface class also allows the main executable to register a function with it that will be executed later (i.e. callback).
// Begin library/dll Public Interface used by an executable
class mydll_interface {
public:
typedef void (*callback_func_t)();
public:
virtual void do_something() = 0;
virtual void registerFunction( callback_func_t ) = 0;
};
static mydll_interface* getMyDllInterface();
// End library/dll Public Interface used by an executable
// Begin library/dll Private implementation
class mydll_implementation : public mydll_interface {
public:
void do_something() {
printf("Hello World\n");
_callback_func();
}
void registerFunction( callback_func_t c) {
_callback_func = c;
}
private:
callback_func_t _callback_func;
};
static mydll_interface* getMyDllInterface() {
return new mydll_implementation();
};
// End library/dll Private implementation
// Begin main executable code
void myMainAppFunc() {
printf("hello World Again\n");
}
int main() {
mydll_interface* iface = getMyDllInterface();
iface->registerFunction(&myMainAppFunc);
iface->do_something();
};
// End main executable code
You pass the pointer to a 3rd-party routine (doesn't have to be a DLL) and it is "called back" when notificastion is required, by the cloned pointer.
It is similar to .net events in that the latter are also a type of a callback.
BTW, DLLs are less popular in C++ than they are in .NET. This is due to impossibility of sharing static variables (and therefore, singletons), the problem also known as lack of dynamic linking (in UNIX systems, this is solved with Shared Objects, which are quite a different concept of dynamically loaded library). Static libraries offer a better code reuse strategy.
Callback functions fulfill a similar purpose to delegates in C#.
For example, the Win32 API provides a timing service, that is accessed by calling SetTimer. SetTimer is exported by a system DLL, but the mechanism is exactly the same as if used in a user dll. In your code you would access the timer by doing something like this:
void
CALLBACK
MyTimerCallback(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
// do something
}
...
TIMERPROC fn = &MyTimerCallback;
int delay = 500;
SetTimer(NULL,0,delay,fn);
Calling SetTimer, and passing in the callback function, allows the operating system to call back into the function each time the timer ticks. Of course, there is no multicast capability here, and, especially in the case of SetTimer, the callback function must be a C function or static class method. There is no class or object instance associated with the function.
A similar pattern could be done in .NET - Im sure .NET has its own Timer paradigm but for a moment we could pretend that it implements a SetTimer function that takes a TimerDelegate.
In user code, in an object you would then define the MyTimerProc as a function with a signature that matches the delegate. And invoke it like this
TimerDelegate d = new TimerDelegate(myObject.MyTimerProc);
SetTimer(0,0,delay,d);
Or, if "timers" was an event that matched the TimerDelegate, then the equivalent C# code would look something like:
timers += new TimerDelegate(myObject.MyTimerProc);
Note: My C# is very rusty so don't take those code samples as any kind of example of either best practices, or even working code :P
When defining your own callback functions it is good practice to always define callback functions to take a void* "context" parameter, as that allows C++ programmers to store their "this" pointer and retrieve it.
// the first parameter to the callback fn is a void* user supplied context parameter
typedef void (CALLBACK* MyCallbackFn)(void* context, int etc);
// and, the dll export function always takes a function pointer, context parameter pair.
DLL_EXPORT void SomeExportedFn(MyCallbackFn, void* context);
A notable example is qSort(), it needs a callback function to compare 2 items.
Callback function can leave some behavior decided at runtime.
If some behavior should be decided by client side dynamically at runtime, then I will ask clients to supply callback functions.

Understanding events and event handlers in C#

I understand the purpose of events, especially within the context of creating user interfaces. I think this is the prototype for creating an event:
public void EventName(object sender, EventArgs e);
What do event handlers do, why are they needed, and how do I to create one?
To understand event handlers, you need to understand delegates. In C#, you can think of a delegate as a pointer (or a reference) to a method. This is useful because the pointer can be passed around as a value.
The central concept of a delegate is its signature, or shape. That is (1) the return type and (2) the input arguments. For example, if we create a delegate void MyDelegate(object sender, EventArgs e), it can only point to methods which return void, and take an object and EventArgs. Kind of like a square hole and a square peg. So we say these methods have the same signature, or shape, as the delegate.
So knowing how to create a reference to a method, let's think about the purpose of events: we want to cause some code to be executed when something happens elsewhere in the system - or "handle the event". To do this, we create specific methods for the code we want to be executed. The glue between the event and the methods to be executed are the delegates. The event must internally store a "list" of pointers to the methods to call when the event is raised.* Of course, to be able to call a method, we need to know what arguments to pass to it! We use the delegate as the "contract" between the event and all the specific methods that will be called.
So the default EventHandler (and many like it) represents a specific shape of method (again, void/object-EventArgs). When you declare an event, you are saying which shape of method (EventHandler) that event will invoke, by specifying a delegate:
//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyEventHandler(string foo);
//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyEventHandler SomethingHappened;
//Here is some code I want to be executed
//when SomethingHappened fires.
void HandleSomethingHappened(string foo)
{
//Do some stuff
}
//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);
//To raise the event within a method.
SomethingHappened("bar");
(*This is the key to events in .NET and peels away the "magic" - an event is really, under the covers, just a list of methods of the same "shape". The list is stored where the event lives. When the event is "raised", it's really just "go through this list of methods and call each one, using these values as the parameters". Assigning an event handler is just a prettier, easier way of adding your method to this list of methods to be called).
C# knows two terms, delegate and event. Let's start with the first one.
Delegate
A delegate is a reference to a method. Just like you can create a reference to an instance:
MyClass instance = myFactory.GetInstance();
You can use a delegate to create an reference to a method:
Action myMethod = myFactory.GetInstance;
Now that you have this reference to a method, you can call the method via the reference:
MyClass instance = myMethod();
But why would you? You can also just call myFactory.GetInstance() directly. In this case you can. However, there are many cases to think about where you don't want the rest of the application to have knowledge of myFactory or to call myFactory.GetInstance() directly.
An obvious one is if you want to be able to replace myFactory.GetInstance() into myOfflineFakeFactory.GetInstance() from one central place (aka factory method pattern).
Factory method pattern
So, if you have a TheOtherClass class and it needs to use the myFactory.GetInstance(), this is how the code will look like without delegates (you'll need to let TheOtherClass know about the type of your myFactory):
TheOtherClass toc;
//...
toc.SetFactory(myFactory);
class TheOtherClass
{
public void SetFactory(MyFactory factory)
{
// set here
}
}
If you'd use delegates, you don't have to expose the type of my factory:
TheOtherClass toc;
//...
Action factoryMethod = myFactory.GetInstance;
toc.SetFactoryMethod(factoryMethod);
class TheOtherClass
{
public void SetFactoryMethod(Action factoryMethod)
{
// set here
}
}
Thus, you can give a delegate to some other class to use, without exposing your type to them. The only thing you're exposing is the signature of your method (how many parameters you have and such).
"Signature of my method", where did I hear that before? O yes, interfaces!!! interfaces describe the signature of a whole class. Think of delegates as describing the signature of only one method!
Another large difference between an interface and a delegate is that when you're writing your class, you don't have to say to C# "this method implements that type of delegate". With interfaces, you do need to say "this class implements that type of an interface".
Further, a delegate reference can (with some restrictions, see below) reference multiple methods (called MulticastDelegate). This means that when you call the delegate, multiple explicitly-attached methods will be executed. An object reference can always only reference to one object.
The restrictions for a MulticastDelegate are that the (method/delegate) signature should not have any return value (void) and the keywords out and ref is not used in the signature. Obviously, you can't call two methods that return a number and expect them to return the same number. Once the signature complies, the delegate is automatically a MulticastDelegate.
Event
Events are just properties (like the get;set; properties to instance fields) which expose subscription to the delegate from other objects. These properties, however, don't support get;set;. Instead, they support add; remove;
So you can have:
Action myField;
public event Action MyProperty
{
add { myField += value; }
remove { myField -= value; }
}
Usage in UI (WinForms,WPF,UWP So on)
So, now we know that a delegate is a reference to a method and that we can have an event to let the world know that they can give us their methods to be referenced from our delegate, and we are a UI button, then: we can ask anyone who is interested in whether I was clicked, to register their method with us (via the event we exposed). We can use all those methods that were given to us and reference them by our delegate. And then, we'll wait and wait.... until a user comes and clicks on that button, then we'll have enough reason to invoke the delegate. And because the delegate references all those methods given to us, all those methods will be invoked. We don't know what those methods do, nor we know which class implements those methods. All we do care about is that someone was interested in us being clicked, and gave us a reference to a method that complied with our desired signature.
Java
Languages like Java don't have delegates. They use interfaces instead. The way they do that is to ask anyone who is interested in 'us being clicked', to implement a certain interface (with a certain method we can call), then give us the whole instance that implements the interface. We keep a list of all objects implementing this interface and can call their 'certain method we can call' whenever we get clicked.
That is actually the declaration for an event handler - a method that will get called when an event is fired. To create an event, you'd write something like this:
public class Foo
{
public event EventHandler MyEvent;
}
And then you can subscribe to the event like this:
Foo foo = new Foo();
foo.MyEvent += new EventHandler(this.OnMyEvent);
With OnMyEvent() defined like this:
private void OnMyEvent(object sender, EventArgs e)
{
MessageBox.Show("MyEvent fired!");
}
Whenever Foo fires off MyEvent, then your OnMyEvent handler will be called.
You don't always have to use an instance of EventArgs as the second parameter. If you want to include additional information, you can use a class derived from EventArgs (EventArgs is the base by convention). For example, if you look at some of the events defined on Control in WinForms, or FrameworkElement in WPF, you can see examples of events that pass additional information to the event handlers.
Here is a code example which may help:
using System;
using System.Collections.Generic;
using System.Text;
namespace Event_Example
{
// First we have to define a delegate that acts as a signature for the
// function that is ultimately called when the event is triggered.
// You will notice that the second parameter is of MyEventArgs type.
// This object will contain information about the triggered event.
public delegate void MyEventHandler(object source, MyEventArgs e);
// This is a class which describes the event to the class that receives it.
// An EventArgs class must always derive from System.EventArgs.
public class MyEventArgs : EventArgs
{
private string EventInfo;
public MyEventArgs(string Text) {
EventInfo = Text;
}
public string GetInfo() {
return EventInfo;
}
}
// This next class is the one which contains an event and triggers it
// once an action is performed. For example, lets trigger this event
// once a variable is incremented over a particular value. Notice the
// event uses the MyEventHandler delegate to create a signature
// for the called function.
public class MyClass
{
public event MyEventHandler OnMaximum;
private int i;
private int Maximum = 10;
public int MyValue
{
get { return i; }
set
{
if(value <= Maximum) {
i = value;
}
else
{
// To make sure we only trigger the event if a handler is present
// we check the event to make sure it's not null.
if(OnMaximum != null) {
OnMaximum(this, new MyEventArgs("You've entered " +
value.ToString() +
", but the maximum is " +
Maximum.ToString()));
}
}
}
}
}
class Program
{
// This is the actual method that will be assigned to the event handler
// within the above class. This is where we perform an action once the
// event has been triggered.
static void MaximumReached(object source, MyEventArgs e) {
Console.WriteLine(e.GetInfo());
}
static void Main(string[] args) {
// Now lets test the event contained in the above class.
MyClass MyObject = new MyClass();
MyObject.OnMaximum += new MyEventHandler(MaximumReached);
for(int x = 0; x <= 15; x++) {
MyObject.MyValue = x;
}
Console.ReadLine();
}
}
}
Just to add to the existing great answers here - building on the code in the accepted one, which uses a delegate void MyEventHandler(string foo)...
Because the compiler knows the delegate type of the SomethingHappened event, this:
myObj.SomethingHappened += HandleSomethingHappened;
Is totally equivalent to:
myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);
And handlers can also be unregistered with -= like this:
// -= removes the handler from the event's list of "listeners":
myObj.SomethingHappened -= HandleSomethingHappened;
For completeness' sake, raising the event can be done like this, only in the class that owns the event:
//Firing the event is done by simply providing the arguments to the event:
var handler = SomethingHappened; // thread-local copy of the event
if (handler != null) // the event is null if there are no listeners!
{
handler("Hi there!");
}
The thread-local copy of the handler is needed to make sure the invocation is thread-safe - otherwise a thread could go and unregister the last handler for the event immediately after we checked if it was null, and we would have a "fun" NullReferenceException there.
C# 6 introduced a nice short hand for this pattern. It uses the null propagation operator.
SomethingHappened?.Invoke("Hi there!");
My understanding of the events is;
Delegate:
A variable to hold reference to method / methods to be executed. This makes it possible to pass around methods like a variable.
Steps for creating and calling the event:
The event is an instance of a delegate
Since an event is an instance of a delegate, then we have to first define the delegate.
Assign the method / methods to be executed when the event is fired (Calling the delegate)
Fire the event (Call the delegate)
Example:
using System;
namespace test{
class MyTestApp{
//The Event Handler declaration
public delegate void EventHandler();
//The Event declaration
public event EventHandler MyHandler;
//The method to call
public void Hello(){
Console.WriteLine("Hello World of events!");
}
public static void Main(){
MyTestApp TestApp = new MyTestApp();
//Assign the method to be called when the event is fired
TestApp.MyHandler = new EventHandler(TestApp.Hello);
//Firing the event
if (TestApp.MyHandler != null){
TestApp.MyHandler();
}
}
}
}
//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyDelegate(string foo);
//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyDelegate MyEvent;
//Here is some code I want to be executed
//when SomethingHappened fires.
void MyEventHandler(string foo)
{
//Do some stuff
}
//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.MyEvent += new MyDelegate (MyEventHandler);
publisher: where the events happen. Publisher should specify which delegate the class is using and generate necessary arguments, pass those arguments and itself to the delegate.
subscriber: where the response happen. Subscriber should specify methods to respond to events. These methods should take the same type of arguments as the delegate. Subscriber then add this method to publisher's delegate.
Therefore, when the event happen in publisher, delegate will receive some event arguments (data, etc), but publisher has no idea what will happen with all these data. Subscribers can create methods in their own class to respond to events in publisher's class, so that subscribers can respond to publisher's events.
I recently made an example of how to use events in c#, and posted it on my blog. I tried to make it as clear as possible, with a very simple example. In case it might help anyone, here it is: http://www.konsfik.com/using-events-in-csharp/
It includes description and source code (with lots of comments), and it mainly focuses on a proper (template - like) usage of events and event handlers.
Some key points are:
Events are like "sub - types of delegates", only more constrained (in a good way). In fact an event's declaration always includes a delegate (EventHandlers are a type of delegate).
Event Handlers are specific types of delegates (you may think of them as a template), which force the user to create events which have a specific "signature". The signature is of the format: (object sender, EventArgs eventarguments).
You may create your own sub-class of EventArgs, in order to include any type of information the event needs to convey. It is not necessary to use EventHandlers when using events. You may completely skip them and use your own kind of delegate in their place.
One key difference between using events and delegates, is that events can only be invoked from within the class that they were declared in, even though they may be declared as public. This is a very important distinction, because it allows your events to be exposed so that they are "connected" to external methods, while at the same time they are protected from "external misuse".
Another thing to know about, in some cases, you have to use the Delegates/Events when you need a low level of coupling !
If you want to use a component in several place in application, you need to make a component with low level of coupling and the specific unconcerned LOGIC must be delegated OUTSIDE of your component ! This ensures that you have a decoupled system and a cleaner code.
In SOLID principle this is the "D", (Dependency inversion principle).
Also known as "IoC", Inversion of control.
You can make "IoC" with Events, Delegates and DI (Dependency Injection).
It's easy to access a method in a child class. But more difficult to access a method in a parent class from child. You have to pass the parent reference to the child ! (or use DI with Interface)
Delegates/Events allows us to communicate from the child to the parent without reference !
In this diagram above, I do not use Delegate/Event and the parent component B has to have a reference of the parent component A to execute the unconcerned business logic in method of A. (high level of coupling)
With this approach, I would have to put all the references of all components that use component B ! :(
In this diagram above, I use Delegate/Event and the component B doesn't have to known A. (low level of coupling)
And you can use your component B anywhere in your application !
I agree with KE50 except that I view the 'event' keyword as an alias for 'ActionCollection' since the event holds a collection of actions to be performed (ie. the delegate).
using System;
namespace test{
class MyTestApp{
//The Event Handler declaration
public delegate void EventAction();
//The Event Action Collection
//Equivalent to
// public List<EventAction> EventActions=new List<EventAction>();
//
public event EventAction EventActions;
//An Action
public void Hello(){
Console.WriteLine("Hello World of events!");
}
//Another Action
public void Goodbye(){
Console.WriteLine("Goodbye Cruel World of events!");
}
public static void Main(){
MyTestApp TestApp = new MyTestApp();
//Add actions to the collection
TestApp.EventActions += TestApp.Hello;
TestApp.EventActions += TestApp.Goodbye;
//Invoke all event actions
if (TestApp.EventActions!= null){
//this peculiar syntax hides the invoke
TestApp.EventActions();
//using the 'ActionCollection' idea:
// foreach(EventAction action in TestApp.EventActions)
// action.Invoke();
}
}
}
}
Great technical answers in the post! I have nothing technically to add to that.
One of the main reasons why new features appear in languages and software in general is marketing or company politics! :-) This must not be under estimated!
I think this applies to certain extend to delegates and events too! i find them useful and add value to the C# language, but on the other hand the Java language decided not to use them! they decided that whatever you are solving with delegates you can already solve with existing features of the language i.e. interfaces e.g.
Now around 2001 Microsoft released the .NET framework and the C# language as a competitor solution to Java, so it was good to have NEW FEATURES that Java doesn't have.
DELEGATES, EVENTS(EVENT HANDLERS/EVENT LISTENERS), CONCEPTS(MULTICASTING/BROADCASTING), ACTION & FUNC
This will be a long one but its the simplest explanation, the problem this is such a nuisance of a topic is because people are just using different words to explain the same thing
First of all, you should know a few things
DELEGATES: It's nothing but a list of methods, why create a list? because when your code is being executed, that list is taken and every method there is executed one by one, just don't listen to textbook definitions take this and you will be all right
also called :
a pointer to a function
a wrapper for a method that can send and receive methods just like a variable
to create a delegate you go
[[access modifier] delegate [return type] [delegate name]([parameters])]
example: public delegate int demo(int a);
now to execute all these methods stored in a list called delegate, you go
1. demo.invoke(a);
2. demo(a); ..... both are valid
using the dot and explicitly saying invoke shines in async programming where you use beginInvoke, but that is out of the scope of this topic
there is one more thing called "Creating an object of the delegate/instantiate Delegate" which is pretty much as it sounds but just to avoid confusion it goes like (for the above example )
example : demo del = new demo(); (or) Public demo del = null;
to add any method to the list called delegate you go += and you also need to remove it once the "requirements of the methods are met" you go -=
(requirements of the methods are met mean you no longer need the method to be active or aka "listening") if you don't remove it, it could cause a "memory leak" meaning your computers ram will be eaten alive, technically allocated memory will not be released
example: say there is a method
public int calculate (int c)
to add this method to delegate you go
1. del = calculate;
2. del += calculate; .... all are valid
to remove
del -= calculate
first of all notice the similarities between the delegate and the method, the return type(output) and the input/parameters are the same, and that is a rule you just cannot add any random or a bunch of methods in a delegate it needs to follow the input-output rule
now why are there 2 different ways to do one thing, the only thing different is the assignment operators (+, =), this introduces a new topic called
EVENTS
which is nothing but a constrained version of a Delegate, It's still a List of methods don't confuse when people explain these terminologies, they change the name, so stick with this to understand
what is the constraint? you cannot do this del = calculate;
what's the harm in it, say a bunch of methods are added to the Delegate(List), you do that 👆 all are wiped out and only a single method "calculate" remains, so to prevent that Events are used,
Event Syntax
Public Event demo del = null;
One more thing you cannot do with events is invoke the delegate directly like demo.invoke since its public it can be accessed and invoked but with events, it can't
now you just add the methods to the event (a special type of delegate)
when to use an event vs a delegate, depends on your situation but pragmatically events are popular
few more keywords
MULTICASTING: nothing but adding more than one method to a delegate
BROADCASTING: adding more than one method to an event
PUBLISHER: the one that executes the method (term used in broadcasting), only a single entity
SUBSCRIBER: The methods that are being executed, can be multiple
LISTENER: the same thing as a subscriber but the term is used in multicasting
EVENT HANDLER: same thing as a subscriber/event listener so what the difference? it's basically the same thing, some say an eventlistener detect for the event to occur and the event handler "handles" or execute the code, ITS THE SAME THING PRACTICALLY!
action and func are just delegates that have been created and instantiated so 2 lines of code in a word, the difference is just in return types
ACTION: does not return anything while taking 0 or more than 1 input
FUNC: returns one thing and takes in parameters
if you don't do good with reading here is the best video on this topic
https://www.youtube.com/playlist?list=PLFt_AvWsXl0dliMtpZC8Qd_ru26785Ih_

Categories

Resources