2

The short version of what I am looking for is this:

I am looking for a mechanism which, given an interface, will dynamically generate a pair of classes for that interface, one multiplexer and one demultiplexer, which will convert calls to/from a general-purpose delegate of the following form: object AnyCall( int method_selector, object[] arguments ). The multiplexer class will accept an AnyCall delegate as a construction-time parameter, and it will implement the interface by delegating every call to the delegate. The demultiplexer class will accept a reference to the interface as a construction-time parameter, and it will implement the delegate by switching on the method selector and invoking the appropriate method of the interface, passing it the parameters that were passed to the delegate.

The long version of what I am looking for is this:

Consider the following interface:

public interface IFooable
{
    void Moo( int i );
    void Boo( string s, bool b );
}

And consider the following class implementing that interface:

public class FooImplementation: IFooable
{
    void IFooable.Moo( int i ) { System.Console.WriteLine( "i: " + i ); }
    void IFooable.Boo( string s, bool b ) { System.Console.WriteLine( "s: " + s + ", b: " + b );  }
}

And then consider the following class making use of the above:

public partial class MuxdemTest
{
    public static void InvokeFoo( IFooable fooable )
    {
        fooable.Moo( 42 );
        fooable.Boo( "fubar!", true );
    }

    public static void Run1()
    {
        IFooable fooable = new FooImplementation();
        InvokeFoo( fooable );
    }
}

Nothing fancy here.

Now let us suppose that instead of giving InvokeFoo() a direct reference to FooImplementation I would like to embed some functionality inbetween the two that would allow me to do some really useful things with the interface method calls, like, say, count the number of times a call was made to one of the methods of the interface; or convert the calls into messages and deliver them to a FooImplementation that resides on a different thread; or on a different continent; or whatever. And of course this inbetween functionality should be able to work on ANY interface, not just IFooable.

In order to achieve this, we need a way to multiplex calls to methods of an interface into invokations of a single general-purpose delegate, and later demultiplex them from invokations to that delegate into interface method calls. The delegate I am thinking of would have the following form:

public delegate object AnyCall( int method_selector, object[] arguments );

So, here is an implementation of a multiplexer for the IFooable interface:

public class MuxForFooable: IFooable
{
    private readonly AnyCall AnyCall;
    public MuxForFooable( AnyCall anycall ) { AnyCall = anycall; }
    void IFooable.Moo( int i ) { AnyCall( 0, new object[]{ i } ); }
    void IFooable.Boo( string s, bool b ) { AnyCall( 1, new object[]{ s, b } ); }
}

And here is an implementation of a demultiplexer for the IFooable interface:

public class DemuxForFooable
{
    public readonly IFooable Target;
    public DemuxForFooable( IFooable target ) { Target = target; }
    public object AnyCall( int method_selector, object[] arguments )
    {
        switch( method_selector )
        {
            case 0: Target.Moo( (int)arguments[0] ); break;
            case 1: Target.Boo( (string)arguments[0], (bool)arguments[1] ); break;
            default: throw new System.InvalidOperationException();
        }
        return null;
    }
}

And here is a piece of code that makes use of the above, achieving exactly the same thing as the Run1() method above, the difference now being that all calls pass through an 'AnyCall' delegate:

public partial class MuxdemTest
{
    public static void Run2()
    {
        IFooable fooable = new FooImplementation();
        DemuxForFooable demux = new DemuxForFooable( fooable );
        MuxForFooable mux = new MuxForFooable( demux.AnyCall );
        InvokeFoo( mux );
    }
}

My only problem is that the classes MuxForFooable and DemuxForFooable have been hand-written, while I want them dynamically generated. Consider the following mock methods that would generate them, and a piece of code that would use those methods:

public partial class MuxdemTest
{
    public static T CreateMux<T>( AnyCall anycall )
    {
        if( typeof(T) == typeof(IFooable) )
            return (T)(IFooable)new MuxForFooable( anycall );
        throw new System.NotImplementedException();
    }

    public static AnyCall CreateDemux<T>( T target )
    {
        if( typeof(T) == typeof(IFooable) )
            return new DemuxForFooable( (IFooable)target ).AnyCall;
        throw new System.NotImplementedException();
    }

    public static void Run3()
    {
        IFooable fooable = new FooImplementation();
        AnyCall demux = CreateDemux<IFooable>( fooable );
        IFooable mux = CreateMux<IFooable>( demux );
        InvokeFoo( mux );
    }
}

Run3() above has exactly the same effect as Run2() and Run1() further above.

So, has anyone ever written or knows how to write actual implementations for CreateMux() and CreateDemux()?

You may assume that the interfaces will contain only methods and no properties, and that all methods will return void and will not accept any "ref" nor "out" parameters. (Even though I would not mind an implementation that would allow these things.)

There are lots of code samples out there that do things similar to what I want, but I am posting this question in the hope that someone has already done exactly what I want to do, because the subject of dynamic code generation is very tricky.

I am aware that what I want can be accomplished with existing proxy frameworks like CastleProxy, but I do not want to use an entire external framework for such a simple task, nor do I want the runtime overhead incurred by the use of such a framework. I looked at the source code of CastleProxy trying to figure out how to use parts of it to do what I want, but I found it way too convoluted to make any sense out of it.

Edit 1:

Six months later, I implemented a tool which does what I was asking for in this question. I am going to publish a paper about it, but before I do that, I need help with the naming, so I opened another question: Need help with naming (marshaling interface calls)

In the mean time, please feel free to add an answer if you have one.

Edit 2:

I decided to call the tool "intertwine", and the operations "entwine" and "untwine". If you want to read about it, here it is: michael.gr - Intertwine: Normalizing Interface Invocations

Community
  • 1
  • 1
Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • Are you sure you want to generate these class pairs? Because if I understand your end goal, you can achieve it with a few lines of code using reflection. The method you're suggesting is unnecessarily complicated. Are you aware of the System.Reflection classes? – Igby Largeman May 27 '11 at 16:41
  • Hey Charles, thank you for your reply. The answer here is PERFORMANCE. Making use of reflection in order to pack the parameters of every single call and then later making use of reflection again in order to unpack them (that's allegedly how System.Delegate.DynamicInvoke() works) would incur a very serious performance penalty. If I receive no answer to this question I think I will do an actual benchmark using the sample code that I provided above and re-post the question as something like "help needed to make this code 1000 times faster". – Mike Nakis May 27 '11 at 18:22
  • You don't want to use framework for something this simple? Anything involving code generation, which seems to be your preferable solution, is going to be complicated up to the point that I would consider it only as a last resort, after all other options were exhausted. – svick May 27 '11 at 19:14
  • Also, make up your mind: is this “very tricky” or “such a simple task”? – svick May 27 '11 at 19:16
  • It is a simple task when compared to the rest of the tasks that make up the project. It is very tricky in terms of actually implementing it. – Mike Nakis May 28 '11 at 04:46
  • Also, in answer to Charles above, placing a call using reflection is rather easy with System.Delegate.DynamicInvoke(), but it is not clear to me how reflection could be used to receive a call. If you have something in mind, please provide an example. – Mike Nakis May 28 '11 at 06:00

2 Answers2

1

In order to achieve this, we need a way to multiplex calls to methods of an interface into invokations of a single general-purpose delegate, and later demultiplex them from invokations to that delegate into interface method calls.

I don't see how this follows from your requirements. I think what you actually want is DynamixProxy, or something similar. With it you can intercept calls to methods, which seems to be exactly what you want. Simple example:

class LoggingIntereceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine(invocation.Method);
        invocation.Proceed();
    }
}

…

public static void Run1()
{
    var generator = new ProxyGenerator();
    IFooable fooable = generator.CreateInterfaceProxyWithTarget<IFooable>(
        new FooImplementation(), new LoggingIntereceptor());
    InvokeFoo(fooable);
}

This gives the following output:

Void Moo(Int32)
i: 42
Void Boo(System.String, Boolean)
s: fubar!, b: True

DynamicProxy generates a type that implements the interface at runtime, so it should be quite fast.

If you don't want to add “an entire framework” to your projects, you don't have to. What you need to run the example above is only one additional assembly: Castle.Core.dll.

svick
  • 236,525
  • 50
  • 385
  • 514
  • svick, thank you very much for your reply, but I am not sure I should accept it because in the statement of the question I specifically said that I do not want to use CastleProxy. You are right, I do not have to use the entire framework. Still, I do not want to use even its 300KB core DLL compiled out of 1MB source code. After studying the LinFu proxy I believe that what I want to do should be achievable with less than 100KB of source code (considerably less, probably) which probably corresponds to something like a 30KB DLL. – Mike Nakis May 28 '11 at 04:44
  • @Mike, I don't understand why do you care so much about the amount of source code and the size of the assembly. Also, if you think you know then answer to this question, you should write it here and accept that. – svick May 28 '11 at 12:29
  • Well, let's say, "size matters" for me because I am old-school. – Mike Nakis May 28 '11 at 16:48
  • @Mike, I don't see that as a valid argument by itself. Yes, in many cases size does matter, for example it makes sense if you don't want your users to download tens of megabytes more, because it would take more time to them. Or you want to use something with less code, because you want to review it all to make sure it's secure. But it's not an argument by itself. – svick May 28 '11 at 17:59
  • @svick After a little more thought on the subject, I came up with the following realization: Even if one was to set out to implement a general purpose interface multiplexer/demultiplexer using dynamic proxies, LinFu and Castle can only be used to implement the multiplexing part: they do not appear to provide any means for implementing the demultiplexing part, so for that one would have to resort to costly APIs that utilize reflection, like MethodInfo.Invoke(). – Mike Nakis May 31 '11 at 03:44
  • The LinFu article [http://www.codeproject.com/KB/cs/LinFuPart1.aspx] actually states that with LinFu you need to use MethodInfo.Invoke() to invoke the target interface, while as far as I can tell about Castle Proxy, even though it does generate the code necessary to invoke the tagret interface without reflection, it does not make this code available through any means other than the interceptor mechanism, which is useless on the target side, where the call is already in the form ''method-identifier, array of boxed arguments'' and it simply needs to be dispatched to the right interface method. – Mike Nakis May 31 '11 at 03:44
  • So, if anyone knows of any way to use Castle Proxy on the target side, please explain. – Mike Nakis May 31 '11 at 03:44
  • @Mike, I thought what you actually wanted was the interceptor, and the de-/multiplexing was just how you thought it would be best achieved. Why can't you use DynamicProxy (or something else, I don't know LinFu) directly? – svick May 31 '11 at 07:43
  • No, what I want to do is explained in the question: `[...] count the number of times a call was made to one of the methods of the interface;` [ok, with a Dynamic Proxy I could do this!] `or convert the calls into messages and deliver them to a FooImplementation that resides on a different thread;` [but what about this?] `or on a different continent.` [or this?]. – Mike Nakis May 31 '11 at 09:55
  • @svick Also, consider this, which is rather well-defined and self-contained: suppose you want to write an event mechanism that works with interfaces, not delegates. That is, when you issue an event you invoke not a delegate but an interface method, and when you register a handler for the event you register not a delegate, but an implementation of the interface. You can certainly do it with an interface multiplexing/demultiplexing mechanism such as the one I am talking about. But can you do it with dynamic proxies? I think not. – Mike Nakis May 31 '11 at 12:07
0

I just read oracle.com: Dynamic Proxy Classes and found out that the java runtime environment offers half of what I am looking for. In their own words:

A dynamic proxy class is a class that implements a list of interfaces specified at runtime such that a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface.

The relevant facility is in the java.lang.reflect package: The Proxy class creates multiplexers, and the InvocationHandler interface plays the role of my AnyCall delegate. Java does not appear to offer any means of creating demultiplexers; why, I do not know.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142