To dynamically create a delegate, you can use Reflection.Emit. Because delegates are special types in .Net, the code to create it is not entirely obvious. The following is the reflected code for the methods used by Expression.Lambda()
. There, it was used to create custom delegate types in situations where there are no Action
or Func
delegates available (more than 17 parameters or parameters using ref
or out
).
class DelegateTypeFactory { private readonly ModuleBuilder m_module; public DelegateTypeFactory() { var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName("DelegateTypeFactory"), AssemblyBuilderAccess.RunAndCollect); m_module = assembly.DefineDynamicModule("DelegateTypeFactory"); } public Type CreateDelegateType(MethodInfo method) { string nameBase = string.Format("{0}{1}", method.DeclaringType.Name, method.Name); string name = GetUniqueName(nameBase); var typeBuilder = m_module.DefineType( name, TypeAttributes.Sealed | TypeAttributes.Public, typeof(MulticastDelegate)); var constructor = typeBuilder.DefineConstructor( MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(object), typeof(IntPtr) }); constructor.SetImplementationFlags(MethodImplAttributes.CodeTypeMask); var parameters = method.GetParameters(); var invokeMethod = typeBuilder.DefineMethod( "Invoke", MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public, method.ReturnType, parameters.Select(p => p.ParameterType).ToArray()); invokeMethod.SetImplementationFlags(MethodImplAttributes.CodeTypeMask); for (int i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; invokeMethod.DefineParameter(i + 1, ParameterAttributes.None, parameter.Name); } return typeBuilder.CreateType(); } private string GetUniqueName(string nameBase) { int number = 2; string name = nameBase; while (m_module.GetType(name) != null) name = nameBase + number++; return name; } }
If you care about performance, you might want to create a cache file of a certain type so as not to create the same delegate type again and again.
The only modification in your code will be the line that creates lambdaExpression
:
LambdaExpression lambdaExpression = Expression.Lambda( s_delegateTypeFactory.CreateDelegateType(method), callExpression, lstParamExpressions);
But you donβt have to deal with Expression
. Delegate.CreateDelegate()
enough:
private static Delegate CreateDelegate(object instance, MethodInfo method) { return Delegate.CreateDelegate( s_delegateTypeFactory.CreateDelegateType(method), instance, method); }
svick source share