473,394 Members | 1,679 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

C# win: Using Reflection to create universal event handlers

Plater
7,872 Expert 4TB
I'm a bit boggled by this since I am rather new to using reflection.
I want to attach an event handler via Reflection (which I can do), but I want to NOT have to know the exact event delegate signature.

For an exmaple, I have a .DLL with the following:
Expand|Select|Wrap|Line Numbers
  1. public delegate CustomEnum CustomEventHandler(Socket s, CustomClass c);
  2. public class myclass
  3. {
  4.    public event CustomEventHandler MyEvent;
  5.    //...
  6. }
  7. public enum CustomEnum
  8. {
  9.    //...
  10. }
  11. public class CustomClass
  12. {
  13.    //...
  14. }
  15.  

I want to be able to:
*load the DLL from reflectionlike a plugin would do (done)
*Instanciate an instance of "myclass" (done)
*Attach an event handler to "MyEvent" (trouble)

If the Event signature was of <SomeRegularType> MyEvent(<SomeRegularType> whatever, etc, etc)
I could cheat and create a handler at design time that matches the signature.
BUT the problem is that the customtypes are ALSO kept in the DLL, so I cannot use the types at design time.

I tried creating an eventhandler like this:
object MyEventHandler(object s, object cc);
But the AddHandler() call fails because the delegate signature is not the same.
(I did a test with a regular event that was void MyEvent(string s) and tried using void MyEventHandler(object s) and it also failed)

So I am questioning how this is done? Do I change the signature in the DLL to be of
object MyEvent(object s, object CC) and then do all the .GetType() matching inside the handler function I create?

Seems like there should be a better way to do this.

Anyone have any thoughts?
Nov 10 '08 #1
10 9542
Plater
7,872 Expert 4TB
Well I am still cheating a lot, but I am making progress. I can now create the event I want, using types contained inside
Given (this is kept in plater.dll):
Expand|Select|Wrap|Line Numbers
  1.  
  2. namespace Plater
  3. {
  4. public delegate CustomEnum CustomEventHandler(Socket s, CustomClass c); 
  5. public class myclass 
  6.    public event CustomEventHandler MyEvent; 
  7.    //... 
  8. public enum CustomEnum 
  9.    //... 
  10. public class CustomClass 
  11.    //... 
  12. }
  13. }
  14.  
  15.  

Expand|Select|Wrap|Line Numbers
  1. Assembly asm = Assembly.LoadFrom("plater.dll");
  2. object[] myparams= new object[0];
  3. object myobj = asm.CreateInstance("Plater.myclass", true, BindingFlags.Default, null, myparams, null, null);
  4.  
  5. Type A = asm.GetType("Plater.CustomEnum");
  6. Type B = typeof(System.Net.Sockets.Socket);
  7. Type C = asm.GetType("Plater.CustomClass");
  8.  
  9. EventInfo peEv2 = myobj.GetType().GetEvent("MyEvent");
  10. MethodInfo RRMeth = typeofClassWithGenericStaticMethod.GetMethod("o_MyEvent", System.Reflection.BindingFlags.Static | BindingFlags.NonPublic);
  11. Type[] RRtypestoSend = new Type[] { A,B,C};
  12. MethodInfo RRMethToAttach = RRMeth.MakeGenericMethod(RRtypestoSend);
  13. Delegate peDel2 = Delegate.CreateDelegate(peEv2.EventHandlerType, RRMethToAttach);
  14. peEv2.AddEventHandler(myobj, peDel2);
  15.  
  16. private static void o_MyEvent<A>(A msg)
  17. {
  18.     MessageBox.Show(msg.GetType().ToString()); 
  19. }
  20.  
The eventhandler DOES get triggered as it should.

Places where I still cheat:
1)Knowing the signature of the event (to create the <A,B,C> eventhandler)
2)Knowing how many types are used (to create the type[] to send)
3)Knowing which types to grab (to do the asm.GetType(string) )

Now, knowing 1) pretty much tells you 2) and 3), but I still think there still should be a way to map an event to a function of maybe:
object myfunc(params object[] paras)
Visual Studio has to know how to read an event and decide on the signature parameters in order to do its auto-create for the eventhandler.
Nov 13 '08 #2
balabaster
797 Expert 512MB
Feel free to tell me if I'm missing what you're asking:

Custom event args usually hold relevant data to the event, and they should inherit from System.EventArgs - if the coder follows standards, which I'm certain you do :oP

So that will allow you the ability of attaching a handler without knowing the correct signature. However - it won't allow you access to the custom properties of e.

a la:
eventhandler MyGenericEventHandler(object Sender, EventArgs e)

object.event += MyGenericEventHandler

In order to access the custom properties, you're going to need to cast e to its native type...which we can't know until we reflect on it.

I've run into this situation before where I needed to be able to cast an object as a type only known at runtime and I came up against a wall. I'll have another play and see what I can come up with but from previous experience I'm doubtful I'm going to be successful...

Or are you trying to grab the event handler that's already defined inside the class and attach it to the parent application? Maybe I'm just not following quite what you're after...
Nov 13 '08 #3
balabaster
797 Expert 512MB
Here's a rather amusing thread that's trying to achieve the same thing - albeit for a different purpose. It's mostly amusing because the person trying to assist seems to completely miss the point of the person trying to get assistance and they spend many posts running around in circles before coming up with no suitable conclusion...

But agreed, this is a situation where you would need this ability.

Although, I guess you could use GetProperty and SetProperty on the reflected object - that should work... which is what they allude to. Not sure if it'll work though yet as I haven't tried it...
Nov 14 '08 #4
balabaster
797 Expert 512MB
I'm not sure if you've come across this yet - but it may be a pointer in the right direction:

http://msdn.microsoft.com/en-us/library/system.reflection.eventinfo.addeventhandler.aspx
Nov 14 '08 #5
Plater
7,872 Expert 4TB
Custom event args usually hold relevant data to the event, and they should inherit from System.EventArgs - if the coder follows standards, which I'm certain you do :oP
While I AM a big fan of coding to standards, the DLL is written for (and needs to continue to work on) an limited system Compact framework, where reflection isn't really feasable.

Perhaps I am a bit to vague for generallity sake.
I wrote a webserver in the form of a dll for a project at work.
The dll has a class that handles all the socket business of reading in the http request and building a custom request object (also contained in the dll).
This class exposes TWO events with the following signatures
void NotifyMessage(string msg)
Plater.ThreadState RequestReceived(Socket s, Plater.RequestObject)

Plater.ThreadState, Plater.RequestObject are contained only in the DLL.

Now with my last post I was able to cheat, and do the Assembly.Load(), create an instance of my class and attach eventhandlers to each event, partially because I knew that I gould call a .GetType() on the ThreadState and other objects, and partially because i abused the generics properties on a method.

Now this is functional for what I was after, I was just wondering for a more universal implementation.
I just want my program to go "hey, the httplistener.dll is here, I might as well run a webserver" or "no dll, guess i will carry on without serving webpages"


EDIT:
Not sure why I am being a helmet and thinking I need to use Reflection in the CE version, it will have a legitamate reference to the dll and can use the types like normal.
I suppose I should rewrite the events to match standard handlers, the event that requires a return value: I can create a custom eventargs that has an object inside it, then I can change that object and read it back again at the palce where i called the event, to mimic a return value right?
Nov 14 '08 #6
balabaster
797 Expert 512MB
EDIT:
Not sure why I am being a helmet and thinking I need to use Reflection in the CE version, it will have a legitamate reference to the dll and can use the types like normal.
I suppose I should rewrite the events to match standard handlers, the event that requires a return value: I can create a custom eventargs that has an object inside it, then I can change that object and read it back again at the palce where i called the event, to mimic a return value right?
I reread your post 3 times before you put that edit and could've sworn I was missing something in your reasoning for needing reflection in the CE version... all the CE version is doing is passing the DLL, right? The version that's being passed the DLL is doing all the work, so yeah, I'd modify the object so that it's coded using the standard whereby e inherits from System.EventArgs and presto you're home free...
Nov 14 '08 #7
Plater
7,872 Expert 4TB
home free...
"Home free" being that I don't need to cheat with the event handlers per-say.
I did discover I rather like this:
Expand|Select|Wrap|Line Numbers
  1. public static Dictionary<string, object> GetProperties(object ReflectedObject)
  2. {
  3.     Dictionary<string, object> retval = new Dictionary<string, object>();
  4.     if (ReflectedObject != null)
  5.     {
  6.         MemberInfo[] mems = ReflectedObject.GetType().GetMembers();
  7.         foreach (MemberInfo mi in mems)
  8.         {
  9.           if (mi.MemberType == MemberTypes.Property)
  10.           {
  11.             string name = mi.Name;
  12.             object o = ReflectedObject.GetType().InvokeMember(name, BindingFlags.GetProperty, null, ReflectedObject, null);
  13.             retval.Add(mi.Name, o);
  14.           }
  15.         }
  16.     }
  17.     return retval;
  18. }
  19.  
  20.  
I know there is a .GetProperties on the Type, but I did it this way in case I wanted some other form of members in there too
Nov 14 '08 #8
balabaster
797 Expert 512MB
Yep... looks like it should work pretty well. You can attach a generic handler, grab e and then just reflect over it to grab the properties as necessary.
Nov 14 '08 #9
balabaster
797 Expert 512MB
Hey man - did you get this working in the end? If so, what did you do?
Nov 17 '08 #10
Plater
7,872 Expert 4TB
It got put on hold for now. It was what I was doing in my spare time at work. Projects have picked up.

The plan is still to re-write the DLL to use the standards event formula. Haven't gotten around to playing with the eventargs as a return statement as well.
Nov 17 '08 #11

Sign in to post your reply or Sign up for a free account.

Similar topics

2
by: D. Patterson | last post by:
Hello all. I've a bit of a problem. I would like to use a method in an object as an event handler. Unfortunately, when the method is called the "this" object references the event trigger rather...
13
by: Charles Law | last post by:
Mr "yEaH rIgHt" posted the following link about a week ago in answer to my question about removing event handlers. > http://www.vbinfozine.com/t_bindevt.shtml Following on from that post, the...
1
by: Samuel R. Neff | last post by:
Is there any way to create a generic event handler that can be subscribed to any event? If I have a sub.. Private Sub DataTable_SomethingChanged(sender As Object, e As System.EventArgs) and...
2
by: mike | last post by:
i'm building an desktop windows app in C#. the main menu for the application will be different depending on the admin rights of the user. i've built the entire app. in delphi and i simply activated...
16
by: Hamed | last post by:
Hello I am developing a utility to be reused in other programs. It I have an object of type Control (a TextBox, ComboBox, etc.) that other programmers use it in applications. they may set some...
14
by: Hamed | last post by:
Hello It seems that I should implement ICloneable to implement my own clone object. the critical point for me is to make a control object based on another control object that all of its event...
5
by: Chris | last post by:
Is there any way you can dynamically add an event and then some code. I get it that you could, in your code, add a control and dynamically add an event handler for e.g. the click event. However the...
2
by: Grzegorz Danowski | last post by:
Hello, I'd like to hide control if any of its event handlers is forbidden for current user (basing on PrincipalPermissionAttribute). How to list all methods that handle given event? I supposed...
3
by: =?Utf-8?B?ZWFndWlsYXI=?= | last post by:
Hi, I am trying to dynamically generate a menu, based on entries on a text or xml file. The text file contains the "tree" after which the menu will need to be created. Something like the...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.