Automatically creating a wrapper to implement an interface

喜你入骨 提交于 2019-11-29 07:38:07

问题


I have some classes that don't implement a certain interface but structurally comply to that interface.

interface IFoo {
    void method();
}

class Bar {  // does not implement IFoo
   public void method() {...}
}

Now, I could write a wrapper around those classes that simply delegate to the wrapped class

class BarWrapper : IFoo {
   Bar bar = new Bar();
   public void method()
   {
      bar.method();
   }
}

But that's lots of tedious work. Can those wrapper classes somehow be generated automatically? Something like:

IFoo foo = CreateWrapper<IFoo>(new Bar());

I'm sure you could do this with Reflection.Emit but I've never used that and it doesn't look very easy at first glance.

Is there an easier way or is there perhaps a library that already implements this?


回答1:


What you're trying to accomplish, is known as duck typing. There are some dedicated libraries that will let you do that, although I haven't used any of them.

With little effort (and some reflection) you can use Castle Dynamic Proxy to do that, using approach outlined here.

If for some reason the interceptor based approach would not be acceptable for you Dynamic Proxy does not support that out of the box (yet), but if you use version 2.2 beta, it would be fairly easy to provide that in a strongly typed manner (without using interceptors), by providing your own proxy type builder (take a look at how mixins are implemented).




回答2:


If you want light and simple Duck typing support, you can also check out: Duck Typing project. It works with .Net 2.0 and newer.

Usage example (taken from David Meyer's site):

public interface ICanAdd
{
    int Add(int x, int y);
}

// Note that MyAdder does NOT implement ICanAdd, 
// but it does define an Add method like the one in ICanAdd:
public class MyAdder
{
    public int Add(int x, int y)
    {
        return x + y;
    }
}

public class Program
{
    void Main()
    {
        MyAdder myAdder = new MyAdder();

        // Even though ICanAdd is not implemented by MyAdder, 
        // we can duck cast it because it implements all the members:
        ICanAdd adder = DuckTyping.Cast<ICanAdd>(myAdder);

        // Now we can call adder as you would any ICanAdd object.
        // Transparently, this call is being forwarded to myAdder.
        int sum = adder.Add(2, 2);
    }
}

Using extension methods, you could simplify it into something like this (simlar to Bart De Smet's syntax)

MyAdder myAdder = new MyAdder(); // this doesn't implement the interface
ICanAdd adder = myAdder.AsIf<ICanAdd>(); // but it quacks like a duck
int sum = adder.Add(2, 2);



回答3:


You could create a new class

class SubBar : IFoo, Bar {
}

and instantiate that (Assuming Bar truly has the ducktype, i.e., the exact IFoo methods).




回答4:


You might want to look at Castle Project's DynamicProxy. That's what Rhino.Mocks uses for its type proxying.

I haven't used it myself, so I don't know how much effort it will require on your part, but I suspect it's a good starting point.




回答5:


Take a look at Introducing “The C# Ducktaper” – Bridging the dynamic world with the static world as this blog post describes exactly what you need.




回答6:


If you are willing to use .NET 4, a solution could be to define the wrapper class as a DynamicObject, and convert the calls to the dynamic methods to calls to the wrapped class by using reflection (I'm not sure if that would actually be less work, anyway; also take in account possible performance concerns associated to the usage of reflection).




回答7:


Although I haven't used them myself I think T4 templates in Visual Studio can be used for code generation of dynamic types link text.




回答8:


Here's a slightly different approach using generics. This would need a little more work thought. You need to implement a wrapper for each Interface and call all the methods with reflection.

class FooWrapper<T> : IFoo
{
   private T obj;

   public FooWrapper(T obj)
   {
      this.obj = obj;
   }

   public void method()
   {
      // call method with reflection
      // obj.method();
   }
}

IFoo foo = new FooWrapper(new Bar());


来源:https://stackoverflow.com/questions/1920222/automatically-creating-a-wrapper-to-implement-an-interface

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!