2013-07-08 29 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.