自动创建包装器以实现接口

我有一些类没有实现某个接口,但在结构上符合该接口。

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

现在,我可以围绕那些简单地委托给包装类的类编写一个包装器

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

但那是繁琐的工作。 那些包装类可以自动生成吗? 就像是:

IFoo foo = CreateWrapper(new Bar());

我相信你可以用Reflection.Emit做到这一点,但我从来没有用过它,乍一看它看起来并不容易。

有没有更简单的方法,或者是否有一个库已经实现了这个?

你想要完成什么,被称为鸭子打字。 有一些专用库可以让你这样做,虽然我还没有使用它们。

只需很少的努力(以及一些反思),您就可以使用Castle Dynamic Proxy来执行此操作,使用此处概述的方法。

如果出于某种原因,基于拦截器的方法对你来说是不可接受的,动态代理不支持开箱即用(但是),但是如果你使用2.2版beta,那么以强类型的方式提供它是相当容易的(不使用拦截器),提供自己的代理类型构建器(看看如何实现mixins)。

如果您想要轻松简单的鸭子打字支持,您还可以查看: 鸭子打字项目 。 它适用于.Net 2.0及更高版本

用法示例(摘自David Meyer的网站 ):

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

使用扩展方法,您可以将其简化为类似的东西(类似于Bart De Smet的语法)

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

你可以创建一个新类

 class SubBar : IFoo, Bar { } 

并实例化(假设Bar真正具有ducktype,即确切的IFoo方法)。

您可能想看看Castle Project的DynamicProxy 。 这就是Rhino.Mocks用于其类型代理的内容。

我自己没有用过,所以我不知道你需要多少努力,但我怀疑这是一个很好的起点。

看一下“The C#Ducktaper”的介绍 – 用静态世界弥合动态世界,因为这篇博文真正描述了你需要的东西。

如果您愿意使用.NET 4,解决方案可能是将包装类定义为DynamicObject ,并使用reflection将对动态方法的调用转换为对包装类的调用(我不确定这是否会实际无论如何,要少工作;还要考虑与reflection的使用相关的可能的性能问题。

虽然我自己没有使用它们,但我认为Visual Studio中的T4模板可用于生成动态类型链接文本的代码。

这是使用generics的略微不同的方法。 这需要更多的工作思路。 您需要为每个接口实现一个包装器,并使用reflection调用所有方法。

 class FooWrapper : 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());