2

I would like to invoke a lambda expression dynamically, but all I got is the methodInfo to do so.

Something like:

Magic.RegisterStaticPacketHandler<TestPacket>((a, b) => { /* Do Stuff */ }); Magic class: public void RegisterStaticPacketHandler<T>(PacketReceivedHandler<T> handler) where T : Packet { //Remember the handler with: handler.GetMethodInfo() } 

And later on I would like to invoke this method. Because PacketReceivedHandler is a delegate, I can get the "MethodInfo" out of it. If I invoke this MethodInfo with just:

methodInfo.Invoke(obj, new object[] { packet, this }); 

I ofc receive an exception, that the given object (obj) doesn't fit. Setting BindingFlags like "NonPublic | Instance | Static" doesnt help either.

UPDATE

PacketReceivedHandler looks as follows:

public delegate void PacketReceivedHandler<T>(T packet, Connection connection) where T : Packet; 

And I save it in my Magic class:

private Dictionary<int, Tuple<MethodInfo, object>> id_methodInfo_object = new Dictionary<int, Tuple<MethodInfo, object>>(); 
  • MethodInfo = The delegate
  • object = Where the delegate comes from
  • id = UID for networking stuff
4
  • 2
    Wouldn't Action<T> be easier? RegisterStaticPacketHandler<T, U>(Action<T, U> handler) and then just do hander([instance of T], [instance of U]) Commented Feb 11, 2016 at 14:21
  • Yeah, invoking lambdas using reflection is tricky, because they may capture a closure, and you have to supply the Target of the delegate Commented Feb 11, 2016 at 14:31
  • Because the generic type <T> is unknown I can't save them into a local variable. Instead of that I just save the methodInfo. So an action wouldn't help me ether. Same situation. Commented Feb 11, 2016 at 14:31
  • @TamasHegedus Target is available to me. Working with fixed methods in the code just works fine. But If I replace the method with a lambda it doesn't work Commented Feb 11, 2016 at 14:32

2 Answers 2

4

You have to save the Target of the delegate besides the method. The easiest is to directly store the whole delegate itself instead of MethodInfo. Something like this:

// Store any lambda or action or anything in their baseclass "Delegate": Delegate act = new Action<int, int>((a, b) => Console.WriteLine(a + b)); // Dynamically invoke like this: act.Method.Invoke(act.Target, new object[] {4, 9}); 

Full example:

class Program { private static List<Delegate> handlers = new List<Delegate>(); public static void RegisterHandler<T>(Action<T> del) { handlers.Add(del); } public static void InvokeHandlers(params object[] args) { foreach (var h in handlers) { h.Method.Invoke(h.Target, args); } } static void Main(string[] args) { RegisterHandler((object a) => Console.WriteLine("#1:" + a)); RegisterHandler((object a) => Console.WriteLine("#2:" + a)); InvokeHandlers("foo"); InvokeHandlers(1234); } } 
Sign up to request clarification or add additional context in comments.

9 Comments

That's why you only store raw Delegates. I included a full example to give you some idea, but to be honest, I don't really understand what you would like to achieve.
Ok, great idea. Doing so following exception occurs: "An die Zielmethode kann nicht gebunden werden, da die Signatur oder Sicherheitstransparenz nicht mit der des Delegattypen kompatibel ist" Something like: "Cant bind to the destination method. The signature or security transparency is not compatable with the delegate" Maybe because the delegate is public, but the lambda is anonymous?
@ThomasChristof Another idea: Just use PacketReceivedHandler<Packet> everywhere, it will work because of delegate covariance.
Ok, I will go for actions. Thank you very much! Was stuck at this problem since 2 days. That really helps me out.
@ThomasChristof The error means that you supplied wrong arguments to the delegate. Could you paste the definition of PacketReceivedHandler<T> and how you try to invoke it?
|
0
public void RegisterStaticPacketHandler<T>(PacketReceivedHandler<T> handler) where T : Packet { _methodInfo = handler.Method; } 

See details in MSDN

1 Comment

Yes, with handler.GetMethodInfo() or handler.Method I receive the MethodInfo. Now how do I continue? methodInfo.Invoke doesnt work for lambdas.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.