来自基类的Unity拦截

本文关键字:Unity 拦截 基类 | 更新日期: 2023-09-27 18:20:46

我想为特定的基类型向Unity声明拦截,并让所有派生类型自动执行该拦截。

我看到两个不同的SO帖子是同一个主题,但都没有我想要的答案:

  • Microsoft Unity基类拦截
    这个告诉我已经知道的;这仍然是不够的信息
  • 派生类中的Unity截取
    这一个非常详细,但属于Unity配置,而不是我使用的命令形式

所以我想展示我的代码,看看我是否能得到一个特定于我的场景的答案。

我有这些课程:

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

ReportAttributePolicyAttributeDrivenPolicy的自定义版本。有关详细信息,请参阅我的Unity Interception博客文章。

显然,我试图实现的场景是:

        var yup = container.Resolve<MyController>();

尽管请求的类型只是从RootController派生的,但我希望根据我的ReportAttributePolicy,用AOP日志来检测解析的类型。

当我执行上述代码时,ReportAttributePolicy上的任何方法都不会执行。这意味着我没有机会创造奇迹。如果我不是在处理继承示例,那么一切都很好。

我如何使它与继承一起工作?

来自基类的Unity拦截

当您调用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);