My understanding is that the Delegate class (not to be confused with the delegate keyword) can only be created from a MethodInfo that could be Invoked. A MethodInfo cannot be invoked if IsGenericMethod is true and ContainsGenericParameters = true. More Information on this.
That being said, if all the types are known at runtime when you need to create the delegate, it is possible to construct a Delegate from them. If for some reason they aren't, you may need to restructure your code so that you create the delegate more closely to its invocation.
static Delegate CreateOpenDelegate(MethodInfo method, object instance, params Type[] genericParameters)
{
var myMethod = method.IsGenericMethod ? method.MakeGenericMethod(genericParameters) : method;
var args = new List<Type>(myMethod.GetParameters()
.Select(param => param.ParameterType));
args.Add(myMethod.ReturnType);
var delegateType = Expression.GetDelegateType(args.ToArray());
return myMethod.CreateDelegate(delegateType, instance);
}
Here is an example using Serialize, but as a static instance on the class Program (just because it was convenient, you can do it as an instance parameter if you prefer).
static void Main(string[] args)
{
var method = typeof(Program).GetMethod("Serialize");
object myCollection = "12345".ToCharArray();
//Get the element type for the array. In this case it is typeof(char)
Delegate test = CreateOpenDelegate(method, null, myCollection.GetType().GetElementType());
test.DynamicInvoke(myCollection);
myCollection = new List<int> { 1, 2, 3, 4, 5 };
//Get the generic argument for the collection type. In this case it is typeof(int)
test = CreateOpenDelegate(method, null, myCollection.GetType().GetGenericArguments()[0]);
test.DynamicInvoke(myCollection);
}
public static void Serialize<TElement>(IList<TElement> value)
{
}
The type of collection may vary depending on your circumstances. I got the type in two different manners, but this too can be abstracted better by calling GetInterfaces() on GetType() and then finding the IList interface and getting the generic type from that interface.
The biggest mistake you may make when first using this is mistakenly passing in the entire IList type as the generic parameter instead of getting the IList generic parameter. At least I know that I still do it frequently.