2010-11-18 5 views
2

Angenommen, wir haben eine Schnittstelle ICat, die von ICatBase und ICatExtension abgeleitet ist, wie unten gezeigt. Für beide unterschiedlichen Schnittstellen ist eine Implementierung verfügbar, CatBase und CatExtension. Wie kann Castle DynamicProxy verwendet werden, um diese in eine Instanz von ICat zu integrieren?Wie können mehrere Schnittstellen mit mehreren Klassen mit DynamicProxy zusammengeführt werden?

Ist es möglich, einen Proxy zu erstellen, in dem ICatExtension von CatExtension implementiert wird und ICatBase von einem Interceptor "implementiert" wird? Wie kann dies erreicht werden?

public interface ICatBase 
{ 
    string Name { get; set; } 
    int Age { get; set; } 
} 

public interface ICatExtension 
{ 
    string Description { get; } 
} 

public interface ICat : ICatBase, ICatExtension 
{ 
} 

public class CatBase : ICatBase 
{ 
    public string Name { get; set; } 
    public int Age { get; set; } 
} 

public class CatExtension : ICatExtension 
{ 
    public string Description 
    { 
     get { return "Furry"; } 
    } 
} 

EDIT

Ich habe Mixins versucht, zu verwenden, um diese Arbeit zu machen, aber der folgende Code führt zu einem NotImplementedException.

var generator = new ProxyGenerator(); 
var options = new ProxyGenerationOptions(); 
options.AddMixinInstance(new CatBase()); 
options.AddMixinInstance(new CatExtension()); 
var cat = generator.CreateInterfaceProxyWithoutTarget<ICat>(options);   
cat.Name = "Joey"; 

Dies ist ein DynamicProxy2 Fehler: Es sind keine interceptors für Methode 'Void set_name (System.String)' festgelegt, die kein Ziel hat. Wenn Methode ohne Ziel aufgerufen wird, gibt es keine Implementierung zum "Fortfahren", und es liegt in der Verantwortung des Interceptors, die Implementierung zu imitieren.

Ich könnte einen benutzerdefinierten Interceptor erstellen, der Aufrufe und Versendungen abfängt an die richtige Schnittstelle, aber ich denke, dass es einen leichteren/besseren Weg geben muss. Hab ich recht?

EDIT # 2

Danke, Krzysztof! Mit den folgenden Zeilen war die Lösung.

var generator = new ProxyGenerator(); 
var options = new ProxyGenerationOptions(); 
options.AddMixinInstance(new CatBase()); 
options.AddMixinInstance(new CatExtension()); 

var cat = (ICat)generator.CreateClassProxyWithTarget(typeof(object), new[] { typeof(ICat)}, new object(), options); 

EDIT # 3

Als letzter Schritt, ich habe einen Windsor Behälter konfiguriert ist, den Proxy aus diesem Beispiel zu erzeugen. Die einzige Möglichkeit, dies zu tun, bestand darin, einen Namen "Cat" anzugeben und eine Instanz von System.Object aufzulösen, indem ich den Namen und das Casting an die Schnittstelle ICat hinterlegte.

WindsorContainer container = new WindsorContainer(); 
container.Register(
    Castle.MicroKernel.Registration.Component.For<object>(). 
     Named("Cat"). 
     Proxy.AdditionalInterfaces(typeof (ICat)). 
     Proxy.MixIns(new CatBase()). 
     Proxy.MixIns(new CatExtension()) 
    ); 

var cat = (ICat)container.Resolve(typeof(object), "Cat"); 

Gibt es eine elegantere Möglichkeit dazu, in dem ich einfach den Behälter für ein ICAT Beispiel fragen, ohne auf einen bestimmten Namen zu beziehen?

+0

Ich erinnere mich nicht, wenn es irgendwo noch dokumentiert ist, aber Sie sehen das richtige Verhalten. "ICat" ohne Ziel hat Vorrang vor Ihren Mixins. Sehen Sie, wie es funktioniert: http://issues.castleproject.org/issue/DYNPROXY-96 –

+0

Okay, also sollte die komplette Schnittstelle "ICat" vom Ziel oder einem der Mixins implementiert worden sein. Aber verbietet es mir nicht, tatsächlich zwei Schnittstellen zu verschmelzen? Ich möchte eine Instanz von "ICat" (kombiniert aus "ICatBase" und "ICatExtension") erhalten, wobei ein Teil der Implementierung ("ICatBase") an ein Ziel/Mixin gesendet wird und der andere ("ICatExtension") an ihn gesendet wird ein anderer Fall. Genauer gesagt werden wir eine Implementierung für ICatExtension bereitstellen, und die ICatBase sollte automatisch mit einem Interceptor generiert werden. – Ringo

+0

nein es bedeutet nur, dass das Ziel Vorrang vor Mixins hat. Machen Sie diese Schnittstelle nicht zum Ziel. Erstellen Sie einen Klassen-Proxy für 'System.Object' und werfen Sie diese Schnittstelle als zusätzliche Schnittstelle zum Proxy, so wird es die niedrigste Priorität haben und die Anrufe gehen zu Mixins –

Antwort

1

Mixins sind, was Sie normalerweise dafür verwenden würden.

+0

Danke für den Zeiger.Ich habe meinen Beitrag bearbeitet und könnte wirklich einige Hinweise verwenden. – Ringo

Verwandte Themen