2013-07-08 109 views
3

我正在为我的DI使用MS WebAPI和Spring.NET,并使用Sprint.NET AOP将方法标记为事务性。Spring.NET AOP代理和MS WebAPI控制器

当我标志着一个“控制器”行动事务,我得到以下错误:

无法转换类型“CompositionAopProxy_13695853c76b40f8b9436e27afa947f0”的对象键入“TPMarketing.PayrollConsole.Web.Rest.Controllers.OrganisationsController”。在System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor处的lambda_method(Closure,Object,Object [])\ r \ n处,“exceptionType”:“System.InvalidCastException”,“stackTrace” <> c_ DisplayClass13.b _c(Object instance,Object [] methodParameters)\ r \ n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance,Object [] arguments)\ r \ n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor。 <> C_ DisplayClass5.b 1-4(个)\ r \ n在System.Threading.Tasks.TaskHelpers.RunSynchronously [TResult(Func`1 FUNC键的CancellationToken的CancellationToken)

这是否意味着你不能使用代理服务器基于Web API控制器的基于Web的AOP?

(我有一个解决办法,我已经作出了自己的“交易”属性,从ActionFilterAttribute继承,只是在Web层使用)

感谢, 乔丹。所以这里

编辑... 我还没来得及检查Marijns建议下面呢,是我有兴趣的解决方法。这是来自我的Action Filter的代码体:(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; } 
+0

相关:http://stackoverflow.com/questions/4280143/asp-net-mvc-controller-declarative-aop-with-spring-net/4346791#4346791 – Marijn

+0

我还没有尝试过使用web api,但前一段时间我已经发布了一个[详细回答这个](http://stackoverflow.com/a/9115510/322283),在“正常“asp.net MVC控制器。 – Marijn

+0

好,非常感谢。 – gusgorman

回答

0

CopositionAopProxy是基于在合同中,是一个实现你的接口,并且不能被投上您的课,因为不是你的类的继承,代理包含您的类的实例,作为物业,但只实现你的类的相同接口。

看AOP documentation

13.1.3. AOP Proxies in Spring.NET

Spring.NET generates AOP proxies at runtime using classes from the System.Reflection.Emit namespace to create necessary IL code for the proxy class. This results in proxies that are very efficient and do not impose any restrictions on the inheritance hierarchy.

Another common approach to AOP proxy implementation in .NET is to use ContextBoundObject and the .NET remoting infrastructure as an interception mechanism. We are not very fond of ContextBoundObject approach because it requires classes that need to be proxied to inherit from the ContextBoundObject either directly or indirectly. In our opinion this an unnecessary restriction that influences how you should design your object model and also excludes applying AOP to "3rd party" classes that are not under your direct control. Context-bound proxies are also an order of magnitude slower than IL-generated proxies, due to the overhead of the context switching and .NET remoting infrastructure.

Spring.NET AOP proxies are also "smart" - in that because proxy configuration is known during proxy generation, the generated proxy can be optimized to invoke target methods via reflection only when necessary (i.e. when there are advices applied to the target method). In all other cases the target method will be called directly, thus avoiding performance hit caused by the reflective invocation.

Finally, Spring.NET AOP proxies will never return a raw reference to a target object. Whenever a target method returns a raw reference to a target object (i.e. "return this;"), AOP proxy will recognize what happened and will replace the return value with a reference to itself instead.

The current implementation of the AOP proxy generator uses object composition to delegate calls from the proxy to a target object, similar to how you would implement a classic Decorator pattern. This means that classes that need to be proxied have to implement one or more interfaces, which is in our opinion not only a less-intruding requirement than ContextBoundObject inheritance requirements, but also a good practice that should be followed anyway for the service classes that are most common targets for AOP proxies. In a future release we will implement proxies using inheritance, which will allow you to proxy classes without interfaces as well and will remove some of the remaining raw reference issues that cannot be solved using composition-based proxies.