2010-08-13 3 views
2

Давайте предположим, что у меня есть следующий интерфейс:Использование Reflection.Emit реализовать интерфейс

public interface IMyService 
{ 
    void SimpleMethod(int id); 
    int Hello(string temp); 

} 

И хочу, чтобы создать класс, который выглядит следующим образом (с помощью отражения испускают).

public class MyServiceProxy : IMyService 
{ 
    IChannel _channel; 

    public MyServiceProxy(IChannel channel) 
    { 
    _channel = channel; 
    } 

    public void SimpleMethod(int id) 
    { 
    _channel.Send(GetType(), "SimpleMethod", new object[]{id}); 
    } 

    public int Hello(string temp) 
    { 
    return (int)_channel.Request(temp); 
    } 
} 

Как это сделать? Я проверил различные динамические прокси и фальшивые фреймворки. Они немного сложны и не очень легко следовать (и я не хочу внешней зависимости). Не должно быть так сложно создать прокси для интерфейса. Может ли кто-нибудь показать мне, как?

+0

Динамическая структура прокси должен быть самый простой способ для достижения этой цели. В противном случае я бы предложил составить пример реализации и проверить сгенерированный IL через .NET Reflector или ILDASM. Это должно дать вам представление о том, что нужно испускать. –

+0

I 100% согласен с Даниэлем. Вы использовали DynamicProxy от Castle? Вы можете получить что-то в нескольких строках кода. Неужели это слишком сложно? (И почему ненависть во внешних зависимостях? Иногда лучший инструмент для работы уже написан и свободен. Почему бы не использовать его?) –

+1

Замок DynamicProxy также является инструментом выбора для меня, в данном случае. Поддержание Reflection.Emit кода не весело. Я уважаю вашу заботу о зависимостях, хотя это Майк Барнет дал нам ILMerge (например, RhinoMocks использует DynamicProxy, но объединяет его в свою сборку, чтобы улучшить повторное использование). – FuleSnabel

ответ

1

В общем, я согласен с комментариями других. Я использовал 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

Смежные вопросы