2009-02-03 4 views
7

IVehicle을 구현 한 클래스 차를 가지고 있고 모든 호출을 차에 전달하고 개수를 계산하는 데 장식 자로 감싸고 싶다면 어떻게 할 것입니까?C#에서 프록시 또는 데코레이터 클래스를 구현하는 가장 짧은 방법은 무엇입니까?

Ruby에서 저는 메소드없이 데코레이터를 구현하고 method_missing을 사용하여 모든 호출을 car 객체로 전달할 수 있습니다.

자바에서는 하나의 메서드를 통해 모든 코드를 실행하고 이후에 전달하는 Proxy 객체를 만들 수 있습니다.

C#에서 할 수있는 비슷한 점이 있습니까?


업데이트 :

answeres과 System.Reflection.Emit에 대해 읽은 것을 i've이에 대한 방법 비슷한 쓸 수 있어야 기반

:

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

유형을 someType의 모든 인터페이스를 구현하고 functionToBeApplied를 실행 한 다음 메서드 호출을 반환하고 객체에 전달합니다.

그냥 그 일을하거나 자기 자신을 써야 할 lib가 있습니까?

답변

4

표준 형식을 사용하려는 경우 프록시를 사용하면 "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); 
    } 
} 

또는 당신은 내가 사용하는, 당신이 그 중 하나를 사용하는 경우

당신이 neccessarily하지만 뛰어난 성능을받지 않습니다 .. 그것은 내 경험에 조금 더 잘 작동 .. 성에서 "DynamicProxy"를 얻을 수 그것들은 주로 처음부터 느려질 가능성이 높은 호출에서 사용됩니다. 그러나 원한다면 시도해 볼 수 있습니다.

마크 솔루션의 성능이 향상됩니다.

2

불행히도 C#에는 mixin 지원이 없습니다. 따라서 모든 메소드를 구현하거나 강력한 리플렉션을 사용해야합니다. 다른 대안합니다 ... FooBase의 사용은 엄격히 선택적임을 주목 다음

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() {...} 
} 

선택 사항 인 프록시/장식 기본 클래스이며; 모든 IFoo가 허용됩니다.

+0

두 단어로 설명해주십시오. "FooBase의 사용은 엄격하게 선택 사항입니다"라는 의미입니까? "어떤 'IFoo'가 허용됩니까? 세미콜론은 내가 별도로 성명서를 읽도록하고 논쟁은 혼란을 가중시키기에 충분하다. cpt.에도 불구하고 명백한 속삭임 : "FooBase는 FooBase가 FooBase와 같은 방식으로"IFoo "를 구현하는 다른 IFoo로 대체 될 수 있다는 것을 의미합니다. 간단하다면 실망하게 될 것입니다. 답은 실망하지 않고 오히려 나의 파라 노야와 함께합니다. 죄송합니다 "verboseness"(지금은이 현상에 해당하는 관용구를 찾아야합니다) –

+1

나는 그것이 당신의 실망스러운 대답이라고 생각합니다. 코드는'IFoo'에만 의존해야합니다. 'FooBase'는'IFoo'를 구현하도록 선택한 코드의 편의입니다. –

+0

감사합니다!** 1) **이 주제는 이미 6 년이 지났으며 그 이후로 아무 것도 바뀌지 않았으며 문제를 해결하는 방법은 여전히 ​​동일합니다. * (나는 C++을 그리워 할 것이라고는 생각하지 못했지만 과부하가있다) * ** 2) ** 나는 그것을 잘못 이해한다 : 추상 클래스로부터 상속받는 것은 나쁜 습관이라고 말하는가? 나는 그들 자신이 기본 구현과의 인터페이스라고 생각하며 매우 편리하다. 'SomeFoo' 인스턴스를 'IFoo'라고 부를 수 있습니다. * (그동안 확장 메서드의 다형성 구현 ms) –