Каков кратчайший способ реализовать класс прокси или декоратора в С#?

StackOverflow https://stackoverflow.com/questions/508110

Вопрос

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

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

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

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


обновлять:

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

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

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

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

Это было полезно?

Решение

Для проксирования вы можете использовать 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» от Castle..По моему опыту, это работает немного лучше..

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

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

Другие советы

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

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top