3

Let's say that I have the following interface:

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

}

And want to generate a class that looks like this (using reflection emit).

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);
  }
}

How do I do it? I've checked various dynamic proxies and mock frameworks. They are bit complex and not very easy to follow (and I do not want an external dependency). It shouldn't be that hard to generate a proxy for an interface. Can anyone show me how?

3
  • A dynamic proxy framework has to be the simplest way to accomplish this. Otherwise, I would suggest compiling your example implementation and inspecting the generated IL via .NET Reflector or ILDASM. That should give you an idea of what would need to be emitted. Commented Aug 13, 2010 at 15:31
  • I 100% agree with Daniel. You've used Castle's DynamicProxy? You can get something going in a few lines of code. Is that really too complex? (And why the hate on external dependencies? Sometimes the best tool for the job has already been written and is free. Why not use it?) Commented Aug 13, 2010 at 15:59
  • 1
    Castle DynamicProxy is the tool of choice for me as well in this case. Maintaining Reflection.Emit code isn't fun. I respect your concern for dependencies though, but that's Mike Barnett has given us ILMerge (for instance RhinoMocks uses DynamicProxy but merges it into their assembly to improve reusability). Commented Aug 13, 2010 at 16:58

1 Answer 1

3

All in all I'm going to agree with others' comments. I've used Castle's DynamicProxy and I think it's wonderful. You can do some really amazing and powerful stuff with it. That said, if you're still considering writing your own, read on:

If you're not excited about emitting IL, there are some new techniques using Lambda expressions that you can use to generate code. None of this is a trivial task, however.

Here's an example of how I've used Lambda expressions to generate a dynamic event handler for any .NET event. You could use a similar technique to generate a dynamic interface implementation.

    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);
    }

Regards,

-Doug

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.