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: -
public delegate CustomEnum CustomEventHandler(Socket s, CustomClass c);
-
public class myclass
-
{
-
public event CustomEventHandler MyEvent;
-
//...
-
}
-
public enum CustomEnum
-
{
-
//...
-
}
-
public class CustomClass
-
{
-
//...
-
}
-
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?
10 9542
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): -
-
namespace Plater
-
{
-
public delegate CustomEnum CustomEventHandler(Socket s, CustomClass c);
-
public class myclass
-
{
-
public event CustomEventHandler MyEvent;
-
//...
-
}
-
public enum CustomEnum
-
{
-
//...
-
}
-
public class CustomClass
-
{
-
//...
-
}
-
}
-
-
-
Assembly asm = Assembly.LoadFrom("plater.dll");
-
object[] myparams= new object[0];
-
object myobj = asm.CreateInstance("Plater.myclass", true, BindingFlags.Default, null, myparams, null, null);
-
-
Type A = asm.GetType("Plater.CustomEnum");
-
Type B = typeof(System.Net.Sockets.Socket);
-
Type C = asm.GetType("Plater.CustomClass");
-
-
EventInfo peEv2 = myobj.GetType().GetEvent("MyEvent");
-
MethodInfo RRMeth = typeofClassWithGenericStaticMethod.GetMethod("o_MyEvent", System.Reflection.BindingFlags.Static | BindingFlags.NonPublic);
-
Type[] RRtypestoSend = new Type[] { A,B,C};
-
MethodInfo RRMethToAttach = RRMeth.MakeGenericMethod(RRtypestoSend);
-
Delegate peDel2 = Delegate.CreateDelegate(peEv2.EventHandlerType, RRMethToAttach);
-
peEv2.AddEventHandler(myobj, peDel2);
-
-
private static void o_MyEvent<A>(A msg)
-
{
-
MessageBox.Show(msg.GetType().ToString());
-
}
-
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.
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...
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...
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
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?
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...
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: -
public static Dictionary<string, object> GetProperties(object ReflectedObject)
-
{
-
Dictionary<string, object> retval = new Dictionary<string, object>();
-
if (ReflectedObject != null)
-
{
-
MemberInfo[] mems = ReflectedObject.GetType().GetMembers();
-
foreach (MemberInfo mi in mems)
-
{
-
if (mi.MemberType == MemberTypes.Property)
-
{
-
string name = mi.Name;
-
object o = ReflectedObject.GetType().InvokeMember(name, BindingFlags.GetProperty, null, ReflectedObject, null);
-
retval.Add(mi.Name, o);
-
}
-
}
-
}
-
return retval;
-
}
-
-
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
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.
Hey man - did you get this working in the end? If so, what did you do?
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.
Sign in to post your reply or Sign up for a free account.
Similar topics
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...
|
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...
|
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...
|
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...
|
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...
|
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...
|
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...
|
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...
|
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...
|
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...
|
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...
|
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
|
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...
|
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...
|
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...
|
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,...
|
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...
|
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...
| |