2012-08-10 29 views
17

Tôi đang cố gắng tìm hiểu về Unity Interceptors và tôi đang gặp khó khăn trong số đó.Sử dụng Unity để chặn tất cả các cuộc gọi đến IMyInterface.SomeMethod

Nói rằng tôi có một giao diện như thế này:

public interface IMyInterface 
{ 
    void SomeMethod(); 
} 

Và tôi có một số không rõ các lớp mà thực hiện giao diện như thế này:

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

Tôi đang tìm kiếm một cách để nói, "cho tất cả các trường hợp của IMyInterface (tôi không muốn liệt kê chúng), khi SomeMethod được gọi là chạy máy đánh chặn của tôi.

Nó là không liệt kê các classe đó là cho tôi troubl e. (Có rất nhiều ví dụ nếu bạn có thể liệt kê tất cả các lớp học của bạn.)

Tôi đã đọc Loại đánh chặn, nhưng tôi dường như không thể tìm hiểu xem nó có làm được những gì tôi đang tìm kiếm không.

Bất kỳ chuyên gia Thống nhất nào có biết cách làm những gì tôi đang tìm kiếm?

Trả lời

0

Thiết lập chặn phải yêu cầu bao gồm nhiều hành động. cấu hình các loại, chính sách và trình xử lý bị chặn.

Đầu tiên xem Using Interception in Applications để biết chi tiết chung về các loại tình huống trong đó hỗ trợ chặn (có hoặc không có vùng chứa DI chẳng hạn). Sau đó, xem Type Interception để biết thêm chi tiết về các loại chặn được hỗ trợ. Đặc biệt lưu ý những gì các interceptor có thể được sử dụng với kiểu class của bạn (nếu không các handler sẽ không bao giờ kích hoạt).

Khi bạn đã quyết định sử dụng trình chặn nào, định cấu hình và tạo trình xử lý cuộc gọi đủ theo các liên kết ở trên. Nếu bạn vẫn gặp sự cố tại thời điểm này, hãy đăng câu hỏi chi tiết hơn. Nếu bạn đã làm điều này, xin vui lòng gửi các cấu hình và mã như "không liệt kê các classe" chỉ đơn giản là không đưa ra bất kỳ gợi ý những gì bạn đang thực sự yêu cầu. Bạn có bằng bất kỳ cơ hội nào có nghĩa là với "liệt kê" mà bạn chỉ định một chính sách hướng thuộc tính và không thể đạt được những gì bạn muốn mà không có nó?

18

Bạn có thể tạo InterceptionBehavior rồi đăng ký nó trên lớp cụ thể. Lưu ý bạn có thể lọc các phương pháp thực hiện trong 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 
    } 
} 

điều khiển đầu ra

Method Called 
Interception Called 

Thông tin thêm về Interception with Unity

9

@GSerjo, đã vạch ra những phương pháp đánh chặn Unity mà hoạt động tốt. Nếu bạn muốn tự động hóa cấu hình của đánh chặn, bạn có thể sử dụng UnityContainerExtension để tự động kết nối tất cả các giao diện cũng như các hành vi. Nếu bạn muốn nhận được vào đánh chặn cụ thể hơn (tên phương pháp, chữ ký, giá trị trả lại vv) thì có thể bạn sẽ cần phải xem xét chính sách Injection (sử dụng quy tắc phù hợp với CallHandlers).

Vì vậy, trong trường hợp này phần mở rộng thùng chứa sẽ trông như thế:

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

Sau đó, bạn có thể sử dụng nó như vậy:

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

Bây giờ khi giao diện được đăng ký các chính sách ngăn chặn thích hợp cũng sẽ có được thêm vào vùng chứa. Vì vậy, trong trường hợp này nếu giao diện được đăng ký là loại IMyInterface hoặc IMyOtherInterface thì các chính sách sẽ được thiết lập để chặn giao diện và các hành vi chặn MyInterceptionBehavior và AnotherInterceptionBehavior cũng sẽ được thêm vào.

Lưu ý rằng Unity 3 (được giải phóng sau câu hỏi/câu trả lời này) đã thêm một tính năng Registration by Convention có thể làm những gì mà tiện ích này thực hiện (mà không phải viết bất kỳ mã tùy chỉnh nào). Ví dụ từ số 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>() 
    }); 
Các vấn đề liên quan