Вы можете создать и скомпилировать выражение LINQ для каждого метода обработчика и кэшировать его для использования в будущем.
public class CompiledDelegate
{
// Assume that there is one one method per handler class type, add method name to dictionary key if necessary
private static Dictionary<Type, CompiledDelegate> _Cache = new Dictionary<Type, CompiledDelegate>();
public static CompiledDelegate Get(Type handlerType, string methodName)
{
CompiledDelegate result;
if (!_Cache.TryGetValue(handlerType, out result))
{
var method = handlerType.GetMethod(methodName);
// determine type of single method parameter
var paramType = method.GetParameters().Single().ParameterType;
// create expression tree (object h, object p) => ((handlerType)h).MethodName((paramType)p)
var exprHandler = Expression.Parameter(typeof(object), "h");
var exprParam = Expression.Parameter(typeof(object), "p");
var lambda = Expression.Lambda(
Expression.Call(
Expression.TypeAs(exprHandler, handlerType), // instance, cast object to handlerType
method, // method
Expression.TypeAs(exprParam, paramType) // parameter, cast object to paramType
),
exprHandler, exprParam // lamda params
);
result = new CompiledDelegate()
{
Method = method,
// compile expression
Compiled = (Action<object, object>)lambda.Compile()
};
_Cache.Add(handlerType, result);
}
return result;
}
public MethodInfo Method { get; private set; }
public Action<object, object> Compiled { get; set; }
}
После того, как у вас есть экземпляр hander, вы можете вызвать его метод через скомпилированный делегат:
CompiledDelegate.Get(handler.GetType(), "handlerSomething").Compiled(handler, mouseEvent)
Вы можете предварительно сгенерировать CompiledDelegate для каждого из обработчиков и добавить их в таблицу отправки вместе с самими обработчиками.
Вызов метода через скомпилированный делегат (после его компиляции, конечно) примерно в 10 раз быстрее, чем вызов того же метода через отражение.