我想向Unity声明对特定基类型的拦截,并自动为所有派生类型保留该拦截。
我看到两个不同的SO帖子是同一主题,但我找不到答案:
所以我想展示我的代码,看看我是否能得到特定于我的情景的答案。
我有这些课程:
public abstract class RootController
{
[Report]
public abstract void Action();
}
public class MyController
{
public void Action()
{
Console.WriteLine("hey");
}
}
[Report]注释是我自己的自定义属性 - 它表示应该将AOP日志记录应用于该方法。我安排将它用于基于策略的拦截,如下所示:
container.AddNewExtension<Interception>();
container.RegisterInstance<InjectionPolicy>(typeof(ReportAttributePolicy).AssemblyQualifiedName, new ReportAttributePolicy());
container.RegisterType<RootController>(
new Interceptor<VirtualMethodInterceptor>(),
new InterceptionBehavior<PolicyInjectionBehavior>()
);
ReportAttributePolicy
是AttributeDrivenPolicy
的自定义版本。有关详细信息,请参阅我的Unity Interception博文。
显然,我正在尝试制作的方案是:
var yup = container.Resolve<MyController>();
即使请求的类型仅来自RootController
,我希望根据我的ReportAttributePolicy
对已解析的类型进行AOP日志记录检测。
当我执行上面的代码时,我的ReportAttributePolicy上没有任何方法被执行。这意味着我没有机会让魔术发生。如果我没有处理继承示例,那么一切正常。
如何使其继承?
答案 0 :(得分:0)
当您致电container.Resolve(...)
时,Unity会查找已配置的拦截器。如果没有,则不执行拦截。对于要求解决的类型,此检查已完成。由于您在MyController
上调用了resolve并且该类型没有配置的拦截器,因此未执行拦截。解决这个问题的唯一方法是注册从RootController
派生的所有控制器并设置拦截器。我已经包含了一些辅助方法来简化这个...
public static IUnityContainer EnableInterception<T>(this IUnityContainer container)
{
container.EnableInterception(typeof (T));
return container;
}
public static IUnityContainer EnableInterception(this IUnityContainer container, Type type)
{
if (type.IsInterface)
container.Configure<Interception>().SetInterceptorFor(type, new InterfaceInterceptor());
else
container.Configure<Interception>().SetInterceptorFor(type, new VirtualMethodInterceptor());
return container;
}
public static IUnityContainer EnableInterception(this IUnityContainer container, IEnumerable<Type> types)
{
foreach (var type in types)
{
container.EnableInterception(type);
}
return container;
}
public static IEnumerable<Type> DerivedFrom<T>(this IEnumerable<Type> types)
{
return types.Where(t => typeof (T).IsAssignableFrom(t) && typeof (T) != t);
}
通过这些扩展以及按惯例方法注册的新Unity 3.0,注册和启用拦截的任务变得非常简单。
var controllers = AllClasses.FromLoadedAssemblies().DerivedFrom<RootController>();
container.RegisterTypes(
controllers,
WithMappings.None,
WithName.Default,
WithLifetime.Transient);
container.EnableInterception(controllers);