In this situation:
public class StrongHooksTest
{
[Fact]
public void NoInvocations()
{
//Hooks.TestHook += (x) => 1234;
var a = Hooks.TestHook.Invoke;
}
static class Hooks
{
public delegate int TestDelegate(int a);
public static TestDelegate TestHook;
}
}
Calling NoInvocations()
results in ArgumentException: Delegate to an instance method cannot have null 'this'.
because Hooks.TestHook
has not been initialized and is therefore null
. (The actual exception does not really make sense, but I understand )
Method groups cannot be made nullable so Hooks.TestHook?.Invoke
does not work.
Now you may ask, why do I need to do this?
I’m trying to dynamically invoke delegates through a wrapper, with strongly typed parameters and return values. This requires the Delegate.Invoke
trick which exposes the delegate’s signature which I then abuse with generic types in my wrapper method.
Example of a wrapper method:
TResult Run<T, TResult>(Func<T, TResult> hook, T arg);
which is called like this:
int result = Run(Hooks.TestHook.Invoke, 1234);
This does work, but only if the delegate field is +=
ed at least once.
What options do I have to deal with uninitialized delegate fields, without requiring the caller of my wrapper to perform additional logic (and without losing strong typing)?