2012-08-10 6 views
17

abzufangen. Ich versuche Unity Interceptors zu lernen, und ich habe es schwer.Verwenden Sie Unity, um alle Aufrufe von IMyInterface.SomeMethod

Sagen, ich habe eine Schnittstelle wie folgt aus:

public interface IMyInterface 
{ 
    void SomeMethod(); 
} 

Und ich habe eine unbekannte Anzahl von Klassen, die diese Schnittstelle wie folgt implementieren:

public class SpecificClass1 : IMyInterface 
{ 
    public void SomeMethod() 
    { 
     Console.WriteLine("Method Called"); 
    } 
} 

ich nach einem Weg suchen zu sagen, "Für alle Instanzen von IMyInterface (ich möchte sie nicht aufzählen), wenn SomeMethod aufgerufen wird, führe meinen Interceptor.

Es ist die Nicht-Enumeration der Klasse, die mir Probleme bereitet e. (Es gibt viele Beispiele, wenn Sie alle Ihre Klassen aufzählen können.)

Ich habe von Typ Interception gelesen, aber ich kann nicht scheinen, herauszufinden, ob es tun wird, was ich suche.

Alle Unity-Experten da draußen wissen, wie ich das mache, wonach ich suche?

Antwort

0

Das Einrichten der Überwachung erfordert mehrere Aktionen inkl. Konfiguration von abgefangenen Typen, Richtlinien und Handlern.

Zuerst finden Sie unter Using Interception in Applications allgemeine Informationen über die Arten von Situationen, in denen Interception unterstützt wird (z. B. mit oder ohne DI-Container). Dann siehe Type Interception für weitere Details über die unterstützten Interceptors. Beachten Sie besonders, welche Interzeptoren mit dem Typ Ihrer Klasse verwendet werden können (andernfalls werden die Handler niemals ausgelöst).

Wenn Sie entschieden haben, welcher Interceptor verwendet werden soll, konfigurieren Sie ihn und erstellen Sie einen ausreichenden Call-Handler wie in den obigen Links beschrieben. Wenn Sie zu diesem Zeitpunkt noch Probleme haben, können Sie eine ausführlichere Frage stellen. Wenn Sie dies bereits getan haben, posten Sie bitte die Configs und den Code als "Nicht-Aufzählung der Klasse" und geben einfach keine Hinweise darauf, was Sie eigentlich fragen. Meinst du mit "Enumeration", dass du eine attributgesteuerte Richtlinie zugewiesen hast und nicht in der Lage bist, das zu erreichen, was du willst?

18

Sie könnten InterceptionBehavior erstellen und dann für eine bestimmte Klasse registrieren. Hinweis können Sie die Ausführung Methoden in Invoke thru IMethodInvocation input

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Microsoft.Practices.Unity; 
using Microsoft.Practices.Unity.InterceptionExtension; 
using NUnit.Framework; 

namespace UnitTests 
{ 
    [TestFixture] 
    public class ForTest 
    { 
     [Test] 
     public void Test() 
     { 
      IUnityContainer container = new UnityContainer().AddNewExtension<Interception>(); 
      container.RegisterType<IMyInterface, SpecificClass1>(
       new Interceptor<InterfaceInterceptor>(), 
       new InterceptionBehavior<MyInterceptionBehavior>()); 
      var myInterface = container.Resolve<IMyInterface>(); 
      myInterface.SomeMethod(); 
     } 
    } 

    public interface IMyInterface 
    { 
     void SomeMethod(); 
    } 

    public class SpecificClass1 : IMyInterface 
    { 
     #region IMyInterface 

     public void SomeMethod() 
     { 
      Console.WriteLine("Method Called"); 
     } 

     #endregion 
    } 

    public class MyInterceptionBehavior : IInterceptionBehavior 
    { 
     public bool WillExecute 
     { 
      get { return true; } 
     } 

     #region IInterceptionBehavior 

     public IEnumerable<Type> GetRequiredInterfaces() 
     { 
      return Enumerable.Empty<Type>(); 
     } 

     public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 
     { 
      IMethodReturn result = getNext()(input, getNext); 
      Console.WriteLine("Interception Called"); 
      return result; 
     } 

     #endregion 
    } 
} 

Konsolenausgabe

Method Called 
Interception Called 

Mehr über Interception with Unity

9

@GSerjo filtern, hat die Unity Interception Ansatz skizziert, die gut funktioniert. Wenn Sie die Abhörkonfiguration automatisieren möchten, können Sie mithilfe von UnityContainerExtension die gesamte Schnittstellenüberwachung sowie die Verhaltensweisen automatisch verbinden. Wenn Sie in spezifischere Interception (Methodennamen, Signaturen, Rückgabewerte usw.) kommen möchten, müssten Sie wahrscheinlich auf Policy Injection schauen (mit Matching-Regeln mit CallHandlers).

Also in diesem Fall der Behälter Erweiterung würde wie folgt aussehen:

IUnityContainer container = new UnityContainer() 
    .AddExtension(new UnityInterfaceInterceptionRegisterer(
     new Type[] { typeof(IMyInterface), 
        typeof(IMyOtherInterface) }, 
     new IInterceptionBehavior[] { new MyInterceptionBehavior(), 
             new AnotherInterceptionBehavior() } 
     )); 

container.RegisterType<IMyInterface, SpecificClass1>(); 

var myInterface = container.Resolve<IMyInterface>(); 
myInterface.SomeMethod(); 

Nun, wenn die Schnittstelle der entsprechende Abhörpolitik auch registriert werden:

public class UnityInterfaceInterceptionRegisterer : UnityContainerExtension 
{ 
    private List<Type> interfaces = new List<Type>(); 
    private List<IInterceptionBehavior> behaviors = 
     new List<IInterceptionBehavior>(); 

    public UnityInterfaceInterceptionRegisterer(Type interfaceType, 
     IInterceptionBehavior interceptionBehavior) 
    { 
     interfaces.Add(interfaceType); 
     behaviors.Add(interceptionBehavior); 
    } 

    public UnityInterfaceInterceptionRegisterer(Type[] interfaces, 
     IInterceptionBehavior[] interceptionBehaviors) 
    {    
     this.interfaces.AddRange(interfaces); 
     this.behaviors.AddRange(interceptionBehaviors); 

     ValidateInterfaces(this.interfaces); 
    } 

    protected override void Initialize() 
    { 
     base.Container.AddNewExtension<Interception>(); 

     base.Context.Registering += 
      new EventHandler<RegisterEventArgs>(this.OnRegister); 
    } 

    private void ValidateInterfaces(List<Type> interfaces) 
    { 
     interfaces.ForEach((i) => 
     { 
      if (!i.IsInterface) 
       throw new ArgumentException("Only interface types may be configured for interface interceptors"); 
     } 
     ); 
    } 

    private bool ShouldIntercept(RegisterEventArgs e) 
    { 
     return e != null && e.TypeFrom != null && 
       e.TypeFrom.IsInterface && interfaces.Contains(e.TypeFrom); 
    } 

    private void OnRegister(object sender, RegisterEventArgs e) 
    { 
     if (ShouldIntercept(e)) 
     { 
      IUnityContainer container = sender as IUnityContainer; 

      var i = new Interceptor<InterfaceInterceptor>(); 
      i.AddPolicies(e.TypeFrom, e.TypeTo, e.Name, Context.Policies); 

      behaviors.ForEach((b) => 
       { 
        var ib = new InterceptionBehavior(b); 
        ib.AddPolicies(e.TypeFrom, e.TypeTo, e.Name, Context.Policies); 
       } 
      ); 
     } 
    } 
} 

Dann können Sie es wie so verwenden könnten dem Container hinzugefügt. Wenn in diesem Fall die registrierte Schnittstelle vom Typ IMyInterface oder IMyOtherInterface ist, werden Richtlinien für das Interception Interface erstellt und die Interception Behaviors MyInterceptionBehavior und AnotherInterceptionBehavior werden ebenfalls hinzugefügt.

Beachten Sie, dass Unity 3 (nach dieser Frage/Antwort veröffentlicht) ein Registration by Convention Feature hinzugefügt hat, das tun kann, was diese Erweiterung tut (ohne benutzerdefinierten Code schreiben zu müssen). Ein Beispiel aus der Developer's Guide to Dependency Injection Using Unity:

var container = new UnityContainer(); 

container.AddNewExtension<Interception>(); 
container.RegisterTypes(
    AllClasses.FromLoadedAssemblies().Where(
     t => t.Namespace == "OtherUnitySamples"), 
    WithMappings.MatchingInterface, 
    getInjectionMembers: t => new InjectionMember[] 
    { 
     new Interceptor<VirtualMethodInterceptor>(), 
     new InterceptionBehavior<LoggingInterceptionBehavior>() 
    }); 
Verwandte Themen