C# Lambda in MethodInfo invocation - c#

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

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);
}
}

public void RegisterStaticPacketHandler<T>(PacketReceivedHandler<T> handler) where T : Packet
{
_methodInfo = handler.Method;
}
See details in MSDN

Related

Reflection - Add a Delegate to another Delegate's invocation list

i am attempting to attach a Delegate to an invocation list of a different delegate.
By that i am achieving a kind of Hook on existing events.
I need to hook up something that runs after each event that is invoked.
The following example works as long as the Delegate exposed by the type and the Action i pass in have the exact same signature.
(On1 and OnAll events are both declared with an Action delegate so it works).
Code : How i hook up an Action with an existing delegate exposed by an event modifier.
public static class ReflectionExtensions
{
public static IEnumerable<EventInfo> GetEvents(this object obj)
{
var events = obj.GetType().GetEvents();
return events;
}
public static void AddHandler(this object obj, Action action)
{
var events = obj.GetEvents();
foreach (var #event in events)
{
#event.AddEventHandler(obj, action);
}
}
}
The Sample :
public class Tester
{
public event Action On1;
public event Action On2;
public void RaiseOn1()
{
On1();
}
public void RaiseOn2()
{
On2();
}
}
class Program
{
static void Main(string[] args)
{
var t = new Tester();
t.On1 += On1;
t.On2 += On2;
t.AddHandler(OnAll);
t.RaiseOn1();
t.RaiseOn2();
}
public void On1() { }
public void On2() { }
public void OnAll() { }
}
The Problem : When the Delegate exposed with an event modifier in Tester does not have the same signature i get a well wanted and obvious exception which states (in my words) that Action can't be added to an invocation list of an Action<int> . makes sense.
Just to be clear I'm describing the following :
public event Action<int> On1;
public void On1(int i){}
What I'm looking for is a way to create another Delegate of the same type as the EventHandlerType. In order to do that i need to create a method with the signature i of EventHandlerType which would internally invoke action.
something like :
public static void AddHandler(this object obj, Action action)
{
var events = obj.GetEvents();
foreach (var #event in events)
{
// method with the signeture of EventHandlerType which does action();
MethodInfo wrapperMethod = WrapAction(#event.EventHandlerType, action);
Delegate handler = Delegate.CreateDelegate(#event.EventHandlerType, action.Target, wrapperMethod);
#event.AddEventHandler(obj, handler);
}
}
This seems to work... There are various comments inside... I'm not sure if this is the best way to do it. I'm building an Expression tree to do the delegate invocation.
public static void AddHandler(this object obj, Action action)
{
var events = obj.GetEvents();
foreach (var #event in events)
{
// Simple case
if (#event.EventHandlerType == typeof(Action))
{
#event.AddEventHandler(obj, action);
}
else
{
// From here: http://stackoverflow.com/a/429564/613130
// We retrieve the parameter types of the event handler
var parameters = #event.EventHandlerType.GetMethod("Invoke").GetParameters();
// We convert it to ParameterExpression[]
ParameterExpression[] parameters2 = Array.ConvertAll(parameters, x => Expression.Parameter(x.ParameterType));
MethodCallExpression call;
// Note that we are "opening" the delegate and using
// directly the Target and the Method! Inside the
// LambdaExpression we will build there won't be a
// delegate call, there will be a method call!
if (action.Target == null)
{
// static case
call = Expression.Call(action.Method);
}
else
{
// instance type
call = Expression.Call(Expression.Constant(action.Target), action.Method);
}
// If you are OK to create a delegate that calls another
// delegate, you can:
// call = Expression.Call(Expression.Constant(action), typeof(Action).GetMethod("Invoke"));
// instead of the big if/else
var lambda = Expression.Lambda(#event.EventHandlerType, call, parameters2);
#event.AddEventHandler(obj, lambda.Compile());
}
}
}

How do I create and call an Action<T> when I only know T at runtime?

How do I create and call a delegate Action<T> when at runtime I'm receiving the delegate as an object and I know type only at runtime?
For example, In Foo, I define my delegate and want to pass it to a method which receives an Action<int> as an object, along with the data to pass to the delegate. It's contrived I know, but it's to demonstrate my problem.
public void Foo()
{
Action<int> handler = i => Console.WriteLine(i + 1);
Process(handler,4)
}
public void Process(object myDelegate, object data)
{
}
and I'd like to call
myDelegate(data)
All the delegate types (Eg. Action<string>) Are actually types that have an Invoke(...) method.
You should look for that invoke method with reflection and call it, It is relatively slow - So watch out.
This should do it :
Action<string> action = s => Console.WriteLine("Hello " + s);
object obj = action;
// Invoking
obj.GetType ().GetMethod ("Invoke").Invoke (obj, new object[] {"World"});
This works too, I don't know what is faster, you should check it out :
Action<string> action = s => Console.WriteLine("Hello " + s);
Delegate obj = action;
obj.DynamicInvoke(new [] { "World" });
So maybe this then:
public void processAction<T>(Action<T> action, T item) {
action(item);
}
Action<int> customAction = (i) => Console.WriteLine(i);
processAction(customAction, 123);
Action<string> customAction2 = (s) => Console.WriteLine(s);
processAction(customAction2, "Frank Borland");
This should work
Action<int> handler = i => Console.WriteLine(i + 1);
Process(handler, 4);
public void Process(object myDelegate, object data)
{
((Delegate)myDelegate).DynamicInvoke(data);
}
You haven't given a whole lot of context here, but can't you rewrite you Process method as:
public void Process<T>(Action<T> myDelegate, T data)
{
myDelegate(data);
}

Function pointers in C#

I suppose in some ways either (or both) Delegate or MethodInfo qualify for this title. However, neither provide the syntactic niceness that I'm looking for. So, in short, Is there some way that I can write the following:
FunctionPointer foo = // whatever, create the function pointer using mechanisms
foo();
I can't use a solid delegate (ie, using the delegate keyword to declare a delegate type) because there is no way of knowing till runtime the exact parameter list. For reference, here's what I've been toying with in LINQPad currently, where B will be (mostly) user generated code, and so will Main, and hence for nicety to my users, I'm trying to remove the .Call:
void Main()
{
A foo = new B();
foo["SomeFuntion"].Call();
}
// Define other methods and classes here
interface IFunction {
void Call();
void Call(params object[] parameters);
}
class A {
private class Function : IFunction {
private MethodInfo _mi;
private A _this;
public Function(A #this, MethodInfo mi) {
_mi = mi;
_this = #this;
}
public void Call() { Call(null); }
public void Call(params object[] parameters) {
_mi.Invoke(_this, parameters);
}
}
Dictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
public A() {
List<MethodInfo> ml = new List<MethodInfo>(this.GetType().GetMethods());
foreach (MethodInfo mi in typeof(Object).GetMethods())
{
for (int i = 0; i < ml.Count; i++)
{
if (ml[i].Name == mi.Name)
ml.RemoveAt(i);
}
}
foreach (MethodInfo mi in ml)
{
functions[mi.Name] = mi;
}
}
public IFunction this[string function] {
get {
if (!functions.ContainsKey(function))
throw new ArgumentException();
return new Function(this, functions[function]);
}
}
}
sealed class B : A {
public void SomeFuntion() {
Console.WriteLine("SomeFunction called.");
}
}
You say you want to keep the number and type of parameters open, but you can do that with a delgate:
public delegate object DynamicFunc(params object[] parameters);
This is exactly the same thing you currently have. Try this:
class Program
{
static void Main(string[] args)
{
DynamicFunc f = par =>
{
foreach (var p in par)
Console.WriteLine(p);
return null;
};
f(1, 4, "Hi");
}
}
You can think of an instance-method delegate as very similar to your Function class: an object an a MethodInfo. So there's no need to rewrite it.
Also function pointers in C and C++ are not any closer to what you need: they cannot be bound to an object instance and function, and also they are statically typed, not dynamically typed.
If you want to "wrap" any other method in a DynamicFunc delegate, try this:
public static DynamicFunc MakeDynamicFunc(object target, MethodInfo method)
{
return par => method.Invoke(target, par);
}
public static void Foo(string s, int n)
{
Console.WriteLine(s);
Console.WriteLine(n);
}
and then:
DynamicFunc f2 = MakeDynamicFunc(null, typeof(Program).GetMethod("Foo"));
f2("test", 100);
Note that I'm using a static method Foo so I pass null for the instance, but if it was an instance method, I'd be passing the object to bind to. Program happens to be the class my static methods are defined in.
Of course, if you pass the wrong argument types then you get errors at runtime. I'd probably look for a way to design your program so that as much type information is captured at compile time as possible.
Here's another bit of code you could use; Reflection is rather slow, so if you expect your Dynamic function calls to be called frequently, you don't want method.Invoke inside the delegate:
public delegate void DynamicAction(params object[] parameters);
static class DynamicActionBuilder
{
public static void PerformAction0(Action a, object[] pars) { a(); }
public static void PerformAction1<T1>(Action<T1> a, object[] p) {
a((T1)p[0]);
}
public static void PerformAction2<T1, T2>(Action<T1, T2> a, object[] p) {
a((T1)p[0], (T2)p[1]);
}
//etc...
public static DynamicAction MakeAction(object target, MethodInfo mi) {
Type[] typeArgs =
mi.GetParameters().Select(pi => pi.ParameterType).ToArray();
string perfActName = "PerformAction" + typeArgs.Length;
MethodInfo performAction =
typeof(DynamicActionBuilder).GetMethod(perfActName);
if (typeArgs.Length != 0)
performAction = performAction.MakeGenericMethod(typeArgs);
Type actionType = performAction.GetParameters()[0].ParameterType;
Delegate action = Delegate.CreateDelegate(actionType, target, mi);
return (DynamicAction)Delegate.CreateDelegate(
typeof(DynamicAction), action, performAction);
}
}
And you could use it like this:
static class TestDab
{
public static void PrintTwo(int a, int b) {
Console.WriteLine("{0} {1}", a, b);
Trace.WriteLine(string.Format("{0} {1}", a, b));//for immediate window.
}
public static void PrintHelloWorld() {
Console.WriteLine("Hello World!");
Trace.WriteLine("Hello World!");//for immediate window.
}
public static void TestIt() {
var dynFunc = DynamicActionBuilder.MakeAction(null,
typeof(TestDab).GetMethod("PrintTwo"));
dynFunc(3, 4);
var dynFunc2 = DynamicActionBuilder.MakeAction(null,
typeof(TestDab).GetMethod("PrintHelloWorld"));
dynFunc2("extraneous","params","allowed"); //you may want to check this.
}
}
This will be quite a bit faster; each dynamic call will involve 1 typecheck per param, 2 delegate calls, and one array construction due to the params-style passing.

How to convert delegate to object in C#?

I am using reflection class to invoke some methods which are on the some other dll.
And one of the methods' parameters are type of delegate.
And I want to invoke this methods by using reflection.
So I need to pass function parameters as object array, but I could not find anything about
how to convert delegate to object.
Thanks in advance
A delegate is an object. Just create the expected delegate as you would normally, and pass it in the parameters array. Here is a rather contrived example:
class Mathematician {
public delegate int MathMethod(int a, int b);
public int DoMaths(int a, int b, MathMethod mathMethod) {
return mathMethod(a, b);
}
}
[Test]
public void Test() {
var math = new Mathematician();
Mathematician.MathMethod addition = (a, b) => a + b;
var method = typeof(Mathematician).GetMethod("DoMaths");
var result = method.Invoke(math, new object[] { 1, 2, addition });
Assert.AreEqual(3, result);
}
Instances of delegates are objects, so this code works (C#3 style) :
Predicate<int> p = (i)=> i >= 42;
Object[] arrayOfObject = new object[] { p };
Hope it helps !
Cédric
Here's an example:
class Program
{
public delegate void TestDel();
public static void ToInvoke(TestDel testDel)
{
testDel();
}
public static void Test()
{
Console.WriteLine("hello world");
}
static void Main(string[] args)
{
TestDel testDel = Program.Test;
typeof(Program).InvokeMember(
"ToInvoke",
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
null,
null,
new object[] { testDel });
}
}
I think this blog post:
C# Reflection - Dealing with Remote Objects
answers your question perfectly.
you can see a delegate as variable type "function". the delegate describes the parameters and return value for a matching function.
delegate void Foo(int a); // here a new delegate obj type Foo has been declared
the above example allows 'Foo' to be used as a data type, the only allowed object that can be matched with a variable of type Foo data type is a method with the same signature so:
void MyFunction(int x);
Foo D = MyFunction; // this is OK
void MyOtherFunction(string x);
Foo D = MyOtherFunction; // will yield an error since not same signature.
Once you have assigned a method to a delegate, you can invoke the method via the delegate:
int n = 1;
D( n ); // or D.Invoke( n );

C#. Add polymorphism for legacy code

Assume we have legacy classes, that can't be modified:
class Foo
{
public void Calculate(int a) { }
}
class Bar
{
public void Compute(int a) {}
}
I want to write a helper with such signature:
void Calc(object obj, int a);
Notice, that the first argument is of type 'object'. The test code should be some like this:
ExampleX.Calc((object)new Foo(), 0);
ExampleX.Calc((object)new Bar(), 0);
The question is, what implementation you can imagine in addition to these:
// Using If/then
class Example1
{
public static void Calc(object obj, int a)
{
if (obj is Foo)
((Foo)obj).Calculate(a);
else if (obj is Bar)
((Bar)obj).Compute(a);
}
}
// Using reflection
class Example2
{
private static Dictionary<Type, MethodInfo> _methods = new Dictionary<Type, MethodInfo>();
static Example2()
{
_methods.Add(typeof(Foo), typeof(Foo).GetMethod("Calculate"));
_methods.Add(typeof(Bar), typeof(Bar).GetMethod("Compute"));
}
public static void Calc(object obj, int a)
{
_methods[obj.GetType()].Invoke(obj, new object[] { a });
}
}
// Using delegates
class Example3
{
private delegate void CalcDelegate(object obj, int a);
private static Dictionary<Type, CalcDelegate> _methods = new Dictionary<Type, CalcDelegate>();
static Example3()
{
_methods.Add(typeof(Foo), (o, a) => ((Foo)o).Calculate(a));
_methods.Add(typeof(Bar), (o, a) => ((Bar)o).Compute(a));
}
public static void Calc(object obj, int a)
{
_methods[obj.GetType()](obj, a);
}
}
// Using Reflection + overloaded methods
class Example4
{
private delegate void CalcDelegate(object obj, int a);
public static void Calc(object obj, int a)
{
Type[] types = new Type[] {
obj.GetType(), typeof(int)
};
typeof(Example4).GetMethod("Calc", types).Invoke(null, new object[] { obj, a });
}
public static void Calc(Foo obj, int a)
{
obj.Calculate(a);
}
public static void Calc(Bar obj, int a)
{
obj.Compute(a);
}
}
Thanks!
Use extension methods to essentially add a new function to an existing type.
http://msdn.microsoft.com/en-us/library/bb383977.aspx
This is how I would write the solution. It reduces the risk of type safety problems in the code and eliminates reflection.
class Example2
{
private static Dictionary<Type, Action<object,int>> _methods = new Dictionary<Type, Action<object,int>>();
static Example2()
{
Add<Foo>( (f,a) => f.Calculate(a) );
Add<Bar>( (b,a) => b.Compute(a) );
}
public static void Calc<TSource>(TSource source, int a)
{
_methods[typeof(TSource)](source,a);
}
public static void Add<TSource>(Action<TSource,int> del)
{
Action<object,int> wrapper = (x,i) => { del((TSource)x, i); };
_methods[typeof(TSource)] = wrapper;
}
}
you could always use the adapter pattern to implement the unchangeable legacy objects, without breaking any objects dependant on its functionality, while still being ableto implement your own (new) functionality to the object.
I would go for example 1, because its the simplest one and most obvious.
I would use Example 2 only if you expect new types of objects with one of these two methods, and example 3 only if you have a lot (tens if not hundreds) of objects and performance starts being an issue.
Edit: Or extension methods if you are .Net 3

Categories

Resources