Spring.NET AOP代理和MS WebAPI控制器

本文关键字:MS WebAPI 控制器 代理 NET AOP Spring | 更新日期: 2023-09-27 18:21:23

我将MS WebAPI与Spring.NET一起用于DI,并使用Sprint.NET AOP将方法标记为事务性方法。

当我将"控制器"操作标记为事务时,我会得到以下错误:

无法将"CompositionAopProxy_13695853c76b40f8b9436e27afa947f0"类型的对象强制转换为"TPMarketing.PayrollConsole.Web.Rest.Controller.OrganizationsController"类型。","exceptionType":"System.InvalidCastException","stackTrace":"位于System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutior的lambda_method(Closure,object,object[])处。<>c_DisplayClass13.b_c(对象实例,Object[]methodParameters)''r''n在System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutior.Execute(对象实例、Object[]参数)''r''n在System.Web.Http.Controllers.Reflected HttpActionDescriptor。<>c_DisplayClass5.b_4()''r''n位于System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 Func,CancellationToken cancellionToken)

这是否意味着您不能将基于代理的AOP与Web API控制器一起使用?

(我有一个变通方法,我为其创建了自己的"Transaction"属性,该属性继承自ActionFilterAttribute,仅用于web层)

谢谢,约旦。

编辑我还没有时间查看下面Marijns的建议,所以这里是我为感兴趣的人提供的解决方法。这是我的操作筛选器中的代码主体:(TransactionManager是Spring.NET IPlatformTransactionManager)。我仍然在服务层中使用普通的Spring.NET Transaction属性,这应该可以很好地发挥作用。

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.ReadOnly = ReadOnly;
        actionContext.Request.Properties[TRANSACTION_KEY] = TransactionManager.GetTransaction(def);
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        ITransactionStatus ts = actionExecutedContext.Request.Properties[TRANSACTION_KEY] as ITransactionStatus;
        if (ts.RollbackOnly || actionExecutedContext.Exception != null)
        {
            TransactionManager.Rollback(ts);
        }
        else
        {
            TransactionManager.Commit(ts);
        }
    }
    public bool ReadOnly { get; set; }

Spring.NET AOP代理和MS WebAPI控制器

CopositionAopProxy基于契约,是接口的实现,不能强制转换为类,因为它不是类的继承,代理包含类的实例作为属性,但只实现类的相同接口。

查看AOP文档:

13.1.3.Spring.NET中的AOP代理

Spring.NET在运行时使用System.Reflection.Emit命名空间中的类生成AOP代理为代理类创建必要的IL代码。这会产生代理非常高效,不会对继承层次结构。

在.NET中实现AOP代理的另一种常见方法是使用ContextBoundObject和.NET远程处理基础结构作为拦截机制。我们不太喜欢ContextBoundObject方法,因为它需要代理到直接或间接从ContextBoundObject继承。在里面我们认为这是一个不必要的限制,会影响你应该设计您的对象模型,并排除将AOP应用于"第三party"类。上下文绑定代理也比生成IL慢一个数量级代理,由于上下文切换和.NET的开销远程处理基础设施。

Spring.NET AOP代理也是"智能的",因为代理配置在代理生成期间是已知的,生成的代理可以优化为仅在以下情况下通过反射调用目标方法必要时(即当有建议应用于目标方法时)。在所有其他情况下,将直接调用目标方法,因此避免反射调用造成的性能打击。

最后,Spring.NET AOP代理永远不会返回对目标对象。每当目标方法返回对目标对象(即"return this;"),AOP代理将识别已发生,并将用对其自身的引用替换返回值相反

AOP代理生成器的当前实现使用对象组合以将来自代理的调用委托给目标对象,类似于实现经典Decorator模式的方式。这意味着需要代理的类必须实现一个或更多的接口,在我们看来,这不仅减少了干扰比ContextBoundObject继承要求更高的要求,而且服务类无论如何都应该遵循的良好做法它们是AOP代理最常见的目标在未来的版本中,我们将使用继承实现代理,这将允许您没有接口的代理类,并且将删除无法使用解决的剩余原始引用问题基于合成的代理