I need to create a delegate to a non-static method of a class. The complications is that at the time of creation I don't have an intance to the class, only its class definition. At call time I do have the instance at hand. Thus I need a way to:
Are both of those possible? How? Note: I'm willing to pay a high perfomance price for number one, but ideally 2 should not be a lot more expensive than a delegate call.
You can use Delegate.CreateDelegate to dynamically construct a delegate for a particular target instance given a MethodInfo. You can look up the MethodInfo with Type.GetMethod (Reflection) and cache it for later use creating the delegate.
For example, this would grab the "GetHashCode" method and bind it to the 'this' instance:
var method = typeof(Object).GetMethod("GetHashCode");
var del = (Func<int>)Delegate.CreateDelegate(typeof(Func<int>), this, method);
There are more subtleties if you have more than one overload of the method, but there are additional GetMethod parameters you can use to disambiguate, if necessary.
What's wrong with just passing an instance in like this?
// Creation.
Action<Foo> bar = foo =>
{
foo.Baz();
};
// Invocation.
bar(new Foo());
It does all you need it to: it encapsulates the logic you want to pass around, and can be invoked on an arbitrary class instance.
Edit: If you're restricted to using a delegate of a certain signature (not allowing an instance to be passed explicitly as a parameter), then you could use some form of "instance provider" which is specified at the time of the delegate's creation, but can be mutated later to provide the appropriate instance when it becomes available, e.g.:
class Provider<T>
{
public T Instance { get; set; }
}
static Action Create(Provider<Foo> provider)
{
return () =>
{
provider.Instance.Baz();
};
}
// ...
// Creation.
var provider = new Provider<Foo>();
var bar = Create(provider);
// Invocation.
provider.Instance = new Foo();
bar();
Of course, this is a bit convoluted, and requires an additional object to be passed around, so perhaps it's not ideal!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With