Автоматически создавая обертку для реализации интерфейса

У меня есть некоторые классы, которые не реализуют определенный интерфейс, но структурно соответствуют тому интерфейсу.

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<IFoo>(new Bar());

Я уверен, что Вы могли сделать это с Отражением. Испустите, но я никогда не использовал это, и это не выглядит очень легким на первый взгляд.

Существует ли более легкий путь или существует ли, возможно, библиотека, которая уже реализует это?

16
задан Ruben Bartelink 11 April 2011 в 08:46
поделиться

8 ответов

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).

8
ответ дан 30 November 2019 в 22:10
поделиться

Если вам нужна легкая и простая поддержка набора текста Duck, вы также можете проверить: Проект Duck Typing . Он работает с .Net 2.0 и новее .

Пример использования (взят с сайта Дэвида Мейера ):

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

Используя методы расширения, вы можете упростить его до чего-то вроде этого ( аналог синтаксиса Барта Де Смета)

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);
6
ответ дан 30 November 2019 в 22:10
поделиться

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
ответ дан 30 November 2019 в 22:10
поделиться

Вы можете посмотреть на DynamicProxy Castle Project. Это то, что Rhino.Mocks использует для проксирования своего типа.

Я не использовал его сам, поэтому не знаю, сколько усилий это потребует с вашей стороны, но я подозреваю, что это хороший отправная точка.

2
ответ дан 30 November 2019 в 22:10
поделиться

Взгляните на Введение в «C # Ducktaper» - мост между динамическим миром и статическим миром , поскольку это сообщение в блоге описывает именно то, что вам нужно.

1
ответ дан 30 November 2019 в 22:10
поделиться

Если вы хотите использовать .NET 4, решением может быть определение класса оболочки как DynamicObject и преобразование вызовов динамических методов в вызовы обернутый класс с использованием отражения (я не уверен, что это действительно потребует меньше работы; также учтите возможные проблемы с производительностью, связанные с использованием отражения).

0
ответ дан 30 November 2019 в 22:10
поделиться

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.

0
ответ дан 30 November 2019 в 22:10
поделиться

Вот несколько другой подход с использованием дженериков. Это потребует дополнительной работы. Вам необходимо реализовать оболочку для каждого интерфейса и вызывать все методы с отражением.

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());
0
ответ дан 30 November 2019 в 22:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: