您可以使用Delegate::CreateDelegate。这比Invoke() 快得多。
var handler = Activator.CreateInstance(typeof(Handler));
var method = type.GetMethod("HandleMessage", BindingFlags.Instance | BindingFlags.Public);
var hook = (Action<object>)Delegate.CreateDelegate(typeof(Action<object>), handler, method);
// Then when you want to invoke it:
hook(new MyMessageType());
随意对其进行基准测试,但我之前已经对其进行了基准测试,并且速度明显更快。
编辑:我现在看到了你的问题,你不能按照我建议的方式去做。
您可以使用表达式编译为您执行调用的委托,这将非常快:
var type = typeof(Handler);
var instance = Activator.CreateInstance(type);
var method = type.GetMethod("HandleMessage", BindingFlags.Instance | BindingFlags.Public);
var originalType = type;
// Loop until we hit the type we want.
while (!(type.IsGenericType) || type.GetGenericTypeDefinition() != typeof(EncasulatedMessageHandler<>))
{
type = type.BaseType;
if(type == null)
throw new ArgumentOutOfRangeException("type");
}
var messageType = type.GetGenericArguments()[0]; // MyMessageType
// Use expression to create a method we can.
var instExpr = Expression.Parameter(typeof(object), "instance");
var paramExpr = Expression.Parameter(typeof(Message), "message");
// (Handler)instance;
var instCastExpr = Expression.Convert(instExpr, originalType);
// (MyMessageType)message
var castExpr = Expression.Convert(paramExpr, messageType);
// ((Handler)inst).HandleMessage((MyMessageType)message)
var invokeExpr = Expression.Call(instCastExpr, method, castExpr);
// if(message is MyMessageType) ((Handler)inst).HandleMessage((MyMessageType)message);
var ifExpr = Expression.IfThen(Expression.TypeIs(paramExpr, messageType), invokeExpr);
// (inst, message) = { if(message is MyMessageType) ((Handler)inst).HandleMessage((MyMessageType)message); }
var lambda = Expression.Lambda<Action<object, Message>>(ifExpr, instExpr, paramExpr);
var compiled = lambda.Compile();
Action<Message> hook = x => compiled(instance, x);
hook(new MyMessageType());
编辑:除了我上面的表达式示例之外,以下内容也可以使用 - 这也是我在这些类型的场景中所做的。
var instance = (IEncapsulatedMessageHandler)Activator.CreateInstance(typeof(Handler));
instance.HandleMessage(new MyMessageType());
public class Message { }
public class MyMessageType : Message { }
public interface IEncapsulatedMessageHandler
{
void HandleMessage(Message message);
}
public abstract class EncasulatedMessageHandler<T> : IEncapsulatedMessageHandler where T : Message
{
public abstract void HandleMessage(T message);
void IEncapsulatedMessageHandler.HandleMessage(Message message)
{
var msg = message as T;
if (msg != null)
HandleMessage(msg);
}
}
public class Handler : EncasulatedMessageHandler<MyMessageType>
{
public override void HandleMessage(MyMessageType message)
{
Console.WriteLine("Yo!");
}
}