2009-02-03 6 views
7

Wenn Sie ein Klassenfahrzeug haben, das IVehicle implementiert und es in einen Dekorateur wickeln will, der alle Anrufe an das Auto weiterleitet und diese zählt, wie würden Sie es tun?Was ist der kürzeste Weg, um eine Proxy oder Decorator-Klasse in C# zu implementieren?

In Ruby konnte ich einfach einen Dekorateur ohne Methoden bauen und method_missing verwenden, um alle Aufrufe an das Autoobjekt weiterzuleiten.

In Java konnte ich ein Proxy-Objekt erstellen, das den gesamten Code über eine Methode ausführt und anschließend weiterleitet.

Gibt es eine ähnliche Sache, die ich in C# machen kann?


Update:

basierend auf dem answeres und was Ive über System.Reflection.Emit lesen sollte es möglich sein, ein Verfahren ähnlich zu, dies zu schreiben:

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

wo Typen implementiert die gesamte Schnittstelle von someType, führt functionToBeApplied aus und leitet den Methodenaufruf an das Objekt weiter, während die Rückgabe zurückgegeben wird.

Gibt es eine Lib, die genau das tut oder müsste ich meine eigene schreiben?

Antwort

4

Für die Proxys können Sie in "RealProxy" schauen, wenn Sie Standardtypen verwenden möchten, es ist ein wenig mühsam zu verwenden (und es erfordert Ihre Klassen von MarshalByRefObject erben).

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

Alternativ können Sie „Dynamic“ von Castle bekommen .. Es funktioniert ein wenig besser in meiner Erfahrung ..

Wenn Sie einer von denen verwenden, werden Sie müssen nicht zwangsläufig große Leistung erhalten, obwohl, ich benutze sie hauptsächlich in Anrufen, die wahrscheinlich in erster Linie langsam sein werden. Aber Sie könnten es ausprobieren, wenn Sie wollen.

Marcs Lösung wird eine bessere Leistung haben.

2

Leider gibt es in C# keine Mixin-Unterstützung. Sie müssen also alle Methoden implementieren oder einige reflection.emit verwenden, um dies zu tun. Die andere Alternative ist ein (optional) Proxy-/decorator Basisklasse ...

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 
} 

dann

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

Anbetracht dessen, dass die Verwendung des FooBase ist streng optional; Jeder IFoo ist erlaubt.

+0

Bitte erläutern Sie in einigen Worten, was bedeutet "Verwendung der' FooBase' ist strikt optional "? Ist es ein Prädikat, dass "irgendein" IFoo "erlaubt ist?" Semikolon lässt mich die Anweisung (en) getrennt lesen und das Argument ist autark, um die Verwirrung hinzuzufügen. trotz cpt. Offensichtliches Flüstern: "Es bedeutet nur, dass' FooBase' durch irgendein anderes 'IFoo' ersetzt werden kann, indem' IFoo' in einer Weise implementiert wird, wie 'FooBase' es tut, ich werde enttäuscht sein, wenn es so einfach ist. nicht enttäuscht von der Antwort, die gut ist, aber eher mit meinem Paranoya. Entschuldigung für "Ausführlichkeit" (jetzt muss ich Idiom finden, dieses Phänomen entsprechend) –

+1

Ich denke, es ist Ihre enttäuschende Antwort; der Code sollte nur von "IFoo" abhängen; 'FooBase' ist nur eine Annehmlichkeit für Code, der' IFoo' implementiert. –

+0

danke!Wenn du Zeit hast, beantworte bitte noch zwei weitere Fragen: ** 1) ** dieses Thema ist schon 6 Jahre alt, sieht danach aus wie sich nichts geändert hat und die Lösungswege sind immer noch gleich? * (dachte nie, ich werde C++ vermissen, aber es hat '->' Überladung) * ** 2) ** irre ich es: Sie sagen, dass es eine schlechte Übung ist, von abstrakten Klassen zu erben? Ich selbst betrachte sie als Schnittstellen zur Standardimplementierung und sie sind sehr praktisch. und kann scheinbar auf 'SomeFoo'-Instanzen als' IFoo' verweisen. * (In der Zwischenzeit implementierte ms den Polymorphismus der Erweiterungsmethoden.) * –

Verwandte Themen