You can just pass the lambda as a parameter, although you will have to qualify it with some delegate type (System.Action
, System.Func
or similar)
This code works for me:
var typeParamOne = typeof(string);
var typeParamTwo = typeof(string);
// we could do new Action<string>(s => MyClass.MyMethod(s));
// but why bother when the method signature matches already
var callbackMethod = new Action<string>(MyClass.MyMethod);
var type = typeof(SomeFrameworkType<,>);
var constructed = type.MakeGenericType(typeParamOne, typeParamTwo);
var instance = Activator.CreateInstance(constructed, callbackMethod);
var castedInstance = (SomeFrameworkType<string, string>)instance;
castedInstance.CallTheCallback();
In fact, we don't need Activator.CreateInstance
at all - we can just get the specific constructor we want, and then invoke it. This would be faster if we were creating many instances of the same type of object. Example:
var type = typeof(SomeFrameworkType<,>);
var constructed = type.MakeGenericType(typeParamOne, typeParamTwo);
var constructor = constructed.GetConstructor(new[]{ typeof(Action<string>) });
var instance = constructor.Invoke(new object[] { callbackMethod });
What if you want to invoke methods on instance
without casting it? Just use InvokeMember
, like this
constructed.InvokeMember(
"CallTheCallback",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public,
null,
instance,
null);
If you don't know what kind of callback method you'll need, then it seems like there will be a problem, because you always want to call MyClass.MyMethod
, which has a fixed known type. for example: if the constructor to SomeFrameworkType<int, int>
requires you to also pass a delegate of type Action<int>
, then this doesn't line up with MyClass.MyMethod
which may take a string parameter.
You'd need to do one of the following:
- create some extra wrapper methods which would convert the int to a string (or similar), and then pass those wrapper methods when creating the instance
- create a bunch of overloads of MyClass.MyMethod
with different parameter types, and have some logic to select the correct one
- make MyClass.MyMethod
generic, and do something like this:
// create the delegate type so we can find the appropriate constructor
var delegateType = typeof(Action<>).MakeGenericType(typeParamOne);
// work out concrete type for calling the generic MyMethod
var myMethodType = typeof(MyClass)
.GetMethod("MyMethod")
.MakeGenericMethod(typeParamOne);
// create an instance of the delegate type wrapping MyMethod so we can pass it to the constructor
var delegateInstance = Delegate.CreateDelegate(delegateType, myMethodType);
var type = typeof(SomeFrameworkType<,>);
var constructed = type.MakeGenericType(typeParamOne, typeParamTwo);
var instance = Activator.CreateInstance(constructed, delegateInstance);