Какой самый короткий способ реализовать класс прокси или декоратор в C #? - PullRequest
7 голосов
/ 03 февраля 2009

Если у вас есть классная машина, которая реализует IVehicle, и вы хотите обернуть ее в декоратор, который перенаправляет все вызовы на машину и считает их, как бы вы это сделали?

В Ruby я мог бы просто создать декоратор без каких-либо методов и использовать method_missing для перенаправления всех вызовов автомобильному объекту.

В Java я мог бы создать объект Proxy, который запускает весь код через один метод и затем пересылает его.

Есть ли что-то похожее, что я могу сделать в C #?


Обновление:

на основе ответов и того, что я читал о System.Reflection.Emit, должно быть возможно написать метод, подобный этому:

Type proxyBuilder(Type someType, delagate functionToBeApplied, Object forward)

где тип реализует весь интерфейс someType, выполняет functionToBeApplied и затем перенаправляет вызов метода к объекту при возврате его возврата.

Есть ли какая-нибудь библиотека, которая делает именно это, или мне придется написать свою собственную?

Ответы [ 2 ]

4 голосов
/ 03 февраля 2009

Для прокси вы можете заглянуть в "RealProxy", если хотите использовать стандартные типы, хотя это немного хлопотно (и требует, чтобы ваши классы наследовали от MarshalByRefObject).

public class TestProxy<T> : RealProxy where T : class
{
    public T Instance { get { return (T)GetTransparentProxy(); } }
    private readonly MarshalByRefObject refObject;
    private readonly string uri;

    public TestProxy() : base(typeof(T))
    {
        refObject = (MarshalByRefObject)Activator.CreateInstance(typeof(T));
        var objRef = RemotingServices.Marshal(refObject);
        uri = objRef.URI;
    }

    // You can find more info on what can be done in here off MSDN.
    public override IMessage Invoke(IMessage message)
    {
        Console.WriteLine("Invoke!");
        message.Properties["__Uri"] = uri;
        return ChannelServices.SyncDispatchMessage(message);
    }
}

В качестве альтернативы вы можете получить "DynamicProxy" от Касла. По моему опыту, он работает немного лучше.

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

Решение Марка будет иметь лучшую производительность.

2 голосов
/ 03 февраля 2009

К сожалению, в C # нет поддержки mixin. Таким образом, вам нужно реализовать все методы или использовать какой-нибудь сверхпрочный отражающий метод для этого. Другой альтернативой является (необязательный) базовый класс прокси / декоратора ...

abstract class FooBase : IFoo {
   protected FooBase(IFoo next) {this.next = next;}
   private readonly IFoo next;
   public virtual void Bar() { // one of the interface methods
       next.Bar();
   }
   public virtual int Blop() { // one of the interface methods
       return next.Blop();
   }
   // etc
}

тогда

class SomeFoo : FooBase {
   public SomeFoo(IFoo next) : base(next) {}
   public override void Bar() {...}
}

отмечая, что использование FooBase строго необязательно; разрешено любое IFoo.

...