5

I've got a need to create a dynamic proxy in C#. I want this class to wrap another class, and take on it's public interface, forwarding calls for those functions:

class MyRootClass
{
    public virtual void Foo()
    {
        Console.Out.WriteLine("Foo!");
    }

}

interface ISecondaryInterface
{
    void Bar();
}

class Wrapper<T> : ISecondaryInterface where T: MyRootClass
{
    public Wrapper(T otherObj)
    {
    }

    public void Bar()
    {
        Console.Out.WriteLine("Bar!");
    }
}

Here's how I want to use it:

Wrapper<MyRootClass> wrappedObj = new Wrapper<MyRootClass>(new MyRootClass());
wrappedObj.Bar();
wrappedObj.Foo();

to produce:

Bar!
Foo!

Any ideas?

What's the easiest way to do this?

What's the best way to do this?

Thanks so much.

UPDATE

I tried following Wernight's recommendation and implement this using C# 4.0 dynamic proxies. Unfortunately, I'm still stuck. The point of the proxy is to mimick the other interface which is (normally, usually) expected. Using DynamicObject requires me to change all the clients of this to use 'dynamic' instead of 'ISecondaryInterface'.

Is there a way to get a proxy object, such that when it wraps an A, it advertises (statically?) that it supports A's interface; and when it wraps a B, it advertises that is supports B's interface?

UPDATE 2

For example:

class MySecretProxy : DynamicObject, ISecondaryInterface
{
    public override void TryInvokeMember(...) { .. }

    // no declaration of Bar -- let it be handled by TryInvokeMember
 }
gap
  • 2,766
  • 2
  • 28
  • 37
  • 1
    How would you even get something like this to compile? Wrapper doesn't have a Foo method.... – BFree Jan 04 '11 at 20:39

5 Answers5

7

.NET 4 DynamicObject can help you achieving that.

Earlier .NET framework can use:

  • Aspect#
  • Encase AOP
  • Spring.NET
  • Aspect.NET
  • AspectDNG
  • Dynamic Proxy
  • Compose*
  • Loom.NET
  • PostSharp

Each of these frameworks make use of a number techniques to the injection of code both before and after execution of a method. These generally fall into 4 categories.

  • MSIL injection – Here we inject MSIL code into the body of the method being executed. (Post sharp)
  • Runtime dynamic injection – Using techniques such as reflection we invoke methods dynamically.
  • Type builder injection – Related to runtime injection, we create a type based on the type we wish to proxy and then marshal requests through this type. (Dynamic Proxy)
  • Container injection – Requests pass through a container which invokes code before and after our method being executed.

See the full article.

I know that Castle Project's Dynamic Proxy is often used (like in Moq just to name one large project).


REPLY TO UPDATED TOPIC

What you wrote will not compile. Dynamic proxies are runtime generated code, so you'll have to create a concrete instance of the class you're proxying some way or another. May be you're looking to do AOP (aspect-oriented programming).

class MySecretProxy<T> : DynamicObject, T where T : new()
{
    private T _instance = new T();

    public override void TryInvokeMember(...) { ... }
}

MySecretProxy<Bar> bar;
Konstantin Spirin
  • 20,609
  • 15
  • 72
  • 90
Wernight
  • 36,122
  • 25
  • 118
  • 131
  • 1
    Nice writeup on the topic, and good real-world example. But I'm still not able to solve my problem (see updates in question). – gap Jul 14 '11 at 16:17
  • 4
    The code you have does not compile, it gives error "Cannot derive from 'T' because it is a type parameter" – Aaron Stainback Mar 13 '13 at 07:21
3

Have you looked at the Castle project's DynamicProxy? It may provide what you're ultimately trying to achieve. See http://www.castleproject.org/dynamicproxy/index.html

It's also open source so you could even fork it if required.

Adam Ralph
  • 29,453
  • 4
  • 60
  • 67
  • 2
    I looked at it briefly, which led me to asking the question here: "What is the easiest way to do this?". It seemed like a pretty large library which I was only going to use one small feature. Is there an easier way? – gap Jan 04 '11 at 20:15
  • 2
    Why are you worried about the size of the library? You only have to use the feature(s) you want. Physically, the file (Castle.Core.dll) is only 290KB. If the library does what you want then using it is almost certainly going to be easier than re-inventing this particular wheel yourself. – Adam Ralph Jan 05 '11 at 07:02
  • By large, I wasn't referring to the size of the assembly, but the sheer number of classes/interfaces which need to be learned & internalized in order to be used properly. It was a training issue, not a space issue. – gap Jul 14 '11 at 16:18
  • If you're only going to use "one small feature" of the library then why do you have to learn about all the other "features" at the same time? If they are currently of no interest to you, you can just ignore them. It's like arguing against using "one small feature" of a library from the .NET framework itself, e.g. mscorlib, just because it has a lot of other "features". – Adam Ralph Jul 15 '11 at 06:14
1

You can do this with RealProxy if the target Type is an interface or derives from MarshalByRefObject.

alexdej
  • 3,751
  • 23
  • 21
0

You may want to look at linfu which contains a dynamic proxy mechanism.

Lee
  • 142,018
  • 20
  • 234
  • 287
0

I know the proxies that used by nhibernate for lazy loading

Castle

Linfu

Spring ByteCode

Jahan Zinedine
  • 14,616
  • 5
  • 46
  • 70