I want to be able to do the equivalent to the following at runtime:
var action = new Action<ANYTHING AT RUNTIME>(obj => Console.WriteLine("Called = " + obj));
I know I need to get the correct type for the Action, but not sure how to get the final bit using Delegate.Create. Type
represent T in the Action definition.
var actionType = typeof(Action<>).MakeGenericType(Type);
var constructor = actionType.GetConstructors()[0];
var @delegate = Delegate.CreateDelegate(actionType, <WHAT GOES HERE>);
the point people seem to be missing is I'm trying to create an instance of Action where T can not be specified statically because it is being used from a class derived from Attribute - this means T could be anything and it can not be defines as a generic definition
Cheers
Thanks to "@prashanth" suggestion, I managed to dynamically create and call an Action<> with a runtime type thanks to the dynamic keyword :
Example with a basic action handler :
Use case :
You can use following code, it works if type can be casted to an object:
However if type is enum or other value type it won't work.
The short answer is to create a delegate
MyActionDelegate
and then use:Here's a working example using a generic class:
Use it like this, which outputs
123
to the console:You'll notice I'm passing two parameters to
Constructor.Invoke
; that's because it turns out that a delegate argument actually compiles as two arguments: the target object of the function, and a pointer to the function. I can't take credit for the fancy footwork there; "borrowed" info from this excellent answer on how to pass a delegate argument using reflection.Use the following code to create a delegate, which is late bound in the type parameter. See also How to: Examine and Instantiate Generic Types with Reflection.
That said, I don't recommend using this method. Instead, use
It offers
The same functionality.
Your original code
"Called = " + obj"
calls.ToString()
on the parameter. So does the above.No performance difference.
If the
obj
parameter is a value type, both variants perform a boxing operation. The boxing in the first is not obvious, but"Called = " + obj"
boxes value types.Shorter and less error-prone.
If you know what the operation you need to perform is and how to perform it regardless of type (as in your example) why not just make a generic method that performs the operation and create your delegate that way?