В общем, я согласен с комментариями других. Я использовал DynamicProxy от Castle, и я думаю, что это замечательно. Вы можете сделать с ним действительно потрясающий и мощный материал. Тем не менее, если вы все еще планируете писать свои собственные, читайте дальше:
Если вы не в восторге от испускания ИЛ, есть несколько новых методов, использующих выражения Лямбда, которые вы можете использовать для генерации кода. Однако ничто из этого не является тривиальной задачей.
Вот пример того, как я использовал лямбда-выражений для создания динамического обработчика событий для любого события .NET. Вы можете использовать подобный метод для генерации реализации динамического интерфейса.
public delegate void CustomEventHandler(object sender, EventArgs e, string eventName);
Delegate CreateEventHandler(EventInfo evt, CustomEventHandler d)
{
var handlerType = evt.EventHandlerType;
var eventParams = handlerType.GetMethod("Invoke").GetParameters();
//lambda: (object x0, EventArgs x1) => d(x0, x1)
// This defines the incoming parameters of our dynamic method.
// The method signature will look something like this:
// void dynamicMethod(object x0, EventArgs<T> x1)
// Each parameter is dynamically determined via the
// EventInfo that was passed.
var parameters = eventParams.Select((p, i) => Expression.Parameter(p.ParameterType, "x" + i)).ToArray();
// Get the MethodInfo for the method we'll be invoking *within* our
// dynamic method. Since we already know the signature of this method,
// we supply the types directly.
MethodInfo targetMethod = d.GetType().GetMethod(
"Invoke",
new Type[] { typeof(object), typeof(EventArgs), typeof(string) }
);
// Next, we need to convert the incoming parameters to the types
// that are expected in our target method. The second parameter,
// in particular, needs to be downcast to an EventArgs object
// in order for the call to succeed.
var p1 = Expression.Convert(parameters[0], typeof(object));
var p2 = Expression.Convert(parameters[1], typeof(EventArgs));
var p3 = Expression.Constant(evt.Name);
// Generate an expression that represents our method call.
// This generates an expression that looks something like:
// d.Invoke(x0, x1, "eventName");
var body = Expression.Call(
Expression.Constant(d),
targetMethod,
p1,
p2,
p3
);
// Convert the entire expression into our shiny new, dynamic method.
var lambda = Expression.Lambda(body, parameters.ToArray());
// Convert our method into a Delegate, so we can use it for event handlers.
return Delegate.CreateDelegate(handlerType, lambda.Compile(), "Invoke", false);
}
С уважением,
-Doug
Динамическая структура прокси должен быть самый простой способ для достижения этой цели. В противном случае я бы предложил составить пример реализации и проверить сгенерированный IL через .NET Reflector или ILDASM. Это должно дать вам представление о том, что нужно испускать. –
I 100% согласен с Даниэлем. Вы использовали DynamicProxy от Castle? Вы можете получить что-то в нескольких строках кода. Неужели это слишком сложно? (И почему ненависть во внешних зависимостях? Иногда лучший инструмент для работы уже написан и свободен. Почему бы не использовать его?) –
Замок DynamicProxy также является инструментом выбора для меня, в данном случае. Поддержание Reflection.Emit кода не весело. Я уважаю вашу заботу о зависимостях, хотя это Майк Барнет дал нам ILMerge (например, RhinoMocks использует DynamicProxy, но объединяет его в свою сборку, чтобы улучшить повторное использование). – FuleSnabel