Как лучше всего реализовать динамический прокси-сервер на С#?

Мне нужно создать динамический прокси на С#. Я хочу, чтобы этот класс обернул другой класс и взял на себя его открытый интерфейс, перенаправляя вызовы для этих функций:

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

Вот как я хочу его использовать:

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

производить:

Bar!
Foo!

Любые идеи?

Какой самый простой способ сделать это?

Как лучше всего это сделать?

Большое спасибо.

ОБНОВЛЕНИЕ

Я попытался следовать рекомендации Вернайта и реализовать это с помощью динамических прокси С# 4.0. К сожалению, я все еще застрял. Смысл прокси-сервера в том, чтобы имитировать другой ожидаемый (обычно, обычно) интерфейс. Использование DynamicObject требует от меня изменить все клиенты этого, чтобы использовать «динамический» вместо «ISecondaryInterface».

Есть ли способ получить прокси-объект, чтобы, когда он обертывал A, он объявлял (статически?), что он поддерживает интерфейс A; и когда он обертывает B, он объявляет, что поддерживает интерфейс B?

ОБНОВЛЕНИЕ 2

Например:

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

    // no declaration of Bar -- let it be handled by TryInvokeMember
 }

person gap    schedule 04.01.2011    source источник
comment
Как бы вы вообще смогли что-то подобное скомпилировать? У оболочки нет метода Foo....   -  person BFree    schedule 04.01.2011


Ответы (5)


.NET 4 DynamicObject поможет вам в этом.

Более ранняя платформа .NET может использовать:

  • Аспект #
  • Обернуть АОП
  • Spring.NET
  • Аспект.NET
  • АспектDNG
  • Динамический прокси
  • Написать*
  • Ткацкий станок.NET
  • PostSharp

Каждая из этих платформ использует ряд методов для внедрения кода как до, так и после выполнения метода. Обычно они делятся на 4 категории.

  • Внедрение MSIL. Здесь мы внедряем код MSIL в тело выполняемого метода. (Пост резкий)
  • Динамическое внедрение во время выполнения. Используя такие методы, как отражение, мы вызываем методы динамически.
  • Внедрение построителя типов. Что касается внедрения во время выполнения, мы создаем тип на основе типа, который мы хотим проксировать, а затем маршалируем запросы через этот тип. (Динамический прокси)
  • Внедрение контейнера. Запросы проходят через контейнер, который вызывает код до и после выполнения нашего метода.

См. полную статью.

Я знаю, что Dynamic Proxy в Castle Project часто используется (например, в Moq, просто чтобы назвать один большой проект).


ОТВЕТ НА ОБНОВЛЕННУЮ ТЕМУ

То, что вы написали, не скомпилируется. Динамические прокси — это код, генерируемый во время выполнения, поэтому вам придется создать конкретный экземпляр класса, который вы тем или иным образом проксируете. Возможно, вы хотите заняться АОП (аспектно-ориентированным программированием).

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

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

MySecretProxy<Bar> bar;
person Wernight    schedule 06.06.2011
comment
Хорошая статья по теме и хороший пример из реальной жизни. Но я все еще не могу решить свою проблему (см. соответствующие обновления). - person gap; 14.07.2011
comment
Код, который у вас есть, не компилируется, он выдает ошибку. Невозможно вывести из «T», потому что это параметр типа. - person Aaron Stainback; 13.03.2013

Вы смотрели DynamicProxy проекта Castle? Это может обеспечить то, чего вы в конечном итоге пытаетесь достичь. См. http://www.castleproject.org/dynamicproxy/index.html.

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

person Adam Ralph    schedule 04.01.2011
comment
Я кратко рассмотрел его, что привело меня к вопросу: как это сделать проще всего? Это казалось довольно большой библиотекой, в которой я собирался использовать только одну небольшую функцию. Есть ли более простой способ? - person gap; 04.01.2011
comment
Почему вас беспокоит размер библиотеки? Вам нужно использовать только те функции, которые вы хотите. Физически файл (Castle.Core.dll) весит всего 290 КБ. Если библиотека делает то, что вы хотите, то использовать ее почти наверняка будет проще, чем заново изобретать это конкретное колесо самостоятельно. - person Adam Ralph; 05.01.2011
comment
По большому счету, я имел в виду не размер сборки, а огромное количество классов/интерфейсов, которые необходимо изучить и усвоить, чтобы правильно использовать. Это был вопрос подготовки, а не космический вопрос. - person gap; 14.07.2011
comment
Если вы собираетесь использовать только одну небольшую функцию библиотеки, то зачем вам одновременно изучать все остальные функции? Если они в данный момент вас не интересуют, вы можете просто игнорировать их. Это все равно, что возражать против использования одной небольшой функции библиотеки из самой среды .NET, например. mscorlib, просто потому, что у него много других функций. - person Adam Ralph; 15.07.2011

Вы можете сделать это с помощью RealProxy, если целевой тип является интерфейсом или производным от MarshalByRefObject.

person alexdej    schedule 14.07.2011

Вы можете посмотреть linfu, который содержит механизм динамического прокси.

person Lee    schedule 04.01.2011

Я знаю прокси, которые использует nhibernate для ленивой загрузки

замок

Линьфу

Весенний байт-код

person Jahan    schedule 04.01.2011