Vac*_*ano 16 .net c# unity-container unity-interception
我正在努力学习Unity拦截器,我正在努力学习它.
说我有这样的界面:
public interface IMyInterface
{
void SomeMethod();
}
Run Code Online (Sandbox Code Playgroud)
我有一个未知数量的类实现该接口,如下所示:
public class SpecificClass1 : IMyInterface
{
public void SomeMethod()
{
Console.WriteLine("Method Called");
}
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种方式来说,"对于IMyInterface的所有实例(我不想枚举它们),当调用SomeMethod时运行我的拦截器.
这是克拉斯的非列举给我带来麻烦.(如果你能列举所有的课程,有很多例子.)
我读过类型拦截,但我似乎无法找出它是否能满足我的要求.
那里的任何Unity专家都知道如何做我想要的东西?
GSe*_*rjo 18
您可以创建InterceptionBehavior然后在特定类上注册它.请注意,您可以Invoke通过过滤执行方法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
}
}
Run Code Online (Sandbox Code Playgroud)
控制台输出
Method Called
Interception Called
Run Code Online (Sandbox Code Playgroud)
更多关于Unity的拦截
@GSerjo概述了Unity拦截方法,该方法运行良好.如果您想自动执行拦截配置,可以使用UnityContainerExtension自动连接所有界面拦截以及行为.如果您想进入更具体的拦截(方法名称,签名,返回值等),那么您可能需要查看策略注入(使用与CallHandlers的匹配规则).
所以在这种情况下,容器扩展看起来像:
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);
}
);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你就可以像这样使用它:
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();
Run Code Online (Sandbox Code Playgroud)
现在,当注册接口时,还将向容器添加适当的拦截策略.因此,在这种情况下,如果注册的接口是IMyInterface或IMyOtherInterface类型,则将设置策略以进行接口拦截,并且还将添加拦截行为MyInterceptionBehavior和AnotherInterceptionBehavior.
请注意,Unity 3(在此问题/答案之后发布)添加了"按惯例注册"功能,该功能可以执行此扩展所执行的操作(无需编写任何自定义代码).开发人员使用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>()
});
Run Code Online (Sandbox Code Playgroud)
设置拦截需要多项操作,包括。拦截类型、策略和处理程序的配置。
首先请参阅在应用程序中使用拦截,了解有关支持拦截的情况类型的一般详细信息(例如,有或没有 DI 容器)。然后,请参阅类型拦截以获取有关支持的类型拦截器的更多详细信息。特别要注意哪些拦截器可以与您的类的类型一起使用(否则处理程序将永远不会触发)。
当您决定使用哪个拦截器时,请配置它并根据上面的链接创建一个足够的调用处理程序。如果此时您仍然遇到问题,请发布更详细的问题。如果您已经这样做了,请发布配置和代码,因为“类的非枚举”根本不会给出您实际要求的任何提示。您是否有可能用“枚举”来表示您分配了属性驱动的策略,并且没有它就无法实现您想要的目标?
| 归档时间: |
|
| 查看次数: |
11971 次 |
| 最近记录: |