Is there a way to store a delegate without binding it to an object like how you can with a MethodInfo? Right now I am storing a MethodInfo so I can give it the object to cal
What you want is called an open instance delegate. It isn't supported directly in the C# language, but the CLR supports it.
Basically, an open instance delegate is the same as a normal delegate, but it takes an extra parameter for this
before the normal parameters, and has a null target (like a delegate for a static method). For instance, the open instance equivalent of Action<T>
would be:
delegate void OpenAction<TThis, T>(TThis @this, T arg);
Here's a complete example:
void Main()
{
MethodInfo sayHelloMethod = typeof(Person).GetMethod("SayHello");
OpenAction<Person, string> action =
(OpenAction<Person, string>)
Delegate.CreateDelegate(
typeof(OpenAction<Person, string>),
null,
sayHelloMethod);
Person joe = new Person { Name = "Joe" };
action(joe, "Jack"); // Prints "Hello Jack, my name is Joe"
}
delegate void OpenAction<TThis, T>(TThis @this, T arg);
class Person
{
public string Name { get; set; }
public void SayHello(string name)
{
Console.WriteLine ("Hi {0}, my name is {1}", name, this.Name);
}
}
Have a look at this article for more details.
Why not simply
Action<T, string> unbound = (This, str) => This.Method(str);
so you can
unbound(instanceA, "hello");
unbound(instanceB, "world");
or even
Action<string> bound = str => unbound(instanceC, str);
A delegate is essentially just a MethodInfo
(actually, a MethodBase
) and an object reference, with some internal pointers for performance. So if you have a MethodInfo
, you essentially have an unbound delegate. What is your specific use case?
You can use the Delegate.CreateDelegate
method to create a strongly-typed delegate for a MethodInfo
.
If you don't know the method's signature at compile-time, you can either create a Func<...>
using Reflection, or create a lambda expression that invokes the MethodInfo
:
MethodInfo methodInfo = ...;
object thisObj = ...;
Func<object[]> callMethod = args => methodInfo.Invoke(thisObj, args);
(This is called currying)
Note that this will still have the performance hit from reflection every time the delegate is called, unlike Delegate.CreateDelegate
.