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