Spring.Net可以作为PostSharp吗?

时间:2010-03-19 22:20:41

标签: .net aop spring.net postsharp

几个月前我发现了PostSharp,有一段时间,它很好。

然后法律回来时回答说他们不喜欢旧版本的许可证。然后该部门告诉我,2.0的价格高得令人无法接受(我们需要的座位数量)......我非常失望,但并不沮丧。我想,不能是唯一这样的框架。

我一直在寻找替代品,但大多数都是死的,维护得不好(特别是在文档部门),学术用途,或者以上所有(我在看你Aspect.Net)

然后我发现了Spring.Net,有一段时间,它很好。

我一直在阅读文档,然后它继续绘制一幅似乎是AOP天堂的超级画面。我不再锁定属性来标记我想要进行代码拦截的位置,但它可以用XML配置,对它的更改不需要重新编译。大。

然后我查看了示例,并在每个使用场景中看到以下内容:

// Create AOP proxy using Spring.NET IoC container.
IApplicationContext ctx = ContextRegistry.GetContext();
ICommand command = (ICommand)ctx["myServiceCommand"];    
command.Execute();
if (command.IsUndoCapable)
{
    command.UnExecute();
}

为什么前两行代码必须存在?它毁了一切。这意味着我不能简单地为用户提供一组方面和属性或XML配置,他们可以通过在适当的方法/类/ etc上粘贴适当的属性或在XML中编辑匹配模式来使用它们。他们必须修改程序逻辑才能使其正常工作!

在这种情况下,有没有办法让Spring.Net像PostSharp一样运行? (即用户只需要添加属性/ XML配置,而不是编辑任何方法的内容。

或者,PostSharp是否有一个有价值且有效的替代品?我在SO上看到了一些题为这样的问题,但是他们都没有真正想要取代PostSharp,他们只是想补充它的功能。我需要完全更换。

2 个答案:

答案 0 :(得分:9)

简而言之,是的,Spring.Net AOP可以按照您使用基于XML的配置描述的方式工作:您不必使用那些最初的两行代码,实际上不鼓励使用基于代码的配置。您可以仅使用基于XML的配置来配置Spring.Net AOP,这实际上是推荐的方法。

有几个步骤:

  1. 创建您的建议:BeforeAdvice,AroundAdvice,AfterReturningAdvice和ThrowsAdvice是支持的建议类型。 AroundAdvice使用AOPAlliance接口,其他使用Spring.AOP接口。
  2. 定义您的切入点
  3. 应用切入点和建议
  4. 示例配置(从实时配置推广):

      <!-- START Spring.Net AOP -->
    
      <object id="beforeAdvice" type="MyBeforeAdvice, MyAOP"></object>
      <object id="beforeAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop">
        <property name="Advice" ref="beforeAdvice" />
      </object>
    
      <object id="returnsAdvice" type="MyAfterReturningAdvice, MyAOP"></object>
      <object id="returnsAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop">
         <property name="Advice" ref="returnsAdvice" />
      </object>
    
      <object id="throwsAdvice" type="MyThrowsAdvice, MyAOP"></object>
      <object id="throwsAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop">
        <property name="Advice" ref="throwsAdvice" />
      </object>
    
    
      <!-- Advise objects -->
      <object type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop">
        <property name="ObjectNames">
          <list>
            <value>*Command</value>
            <value>...</value>
          </list>
        </property>
        <property name="InterceptorNames">
          <list>
            <value>beforeAdvisor</value>
            <value>returnsAdvisor</value>
            <value>throwsAdvisor</value>
          </list>
        </property>
      </object> 
    
    
      <!-- END Spring.Net AOP -->
    

    编织在运行时执行,非常快速且不引人注目。

    希望这是有用的,

    安德鲁

答案 1 :(得分:2)

我认为您正在寻找lookup-method injection功能。

您已经在一开始就在某处加载了Spring.NET应用程序上下文。基于代码的对Spring.NET的依赖很少。问题是,无论你需要一个(建议的)服务,你明确依赖Spring.NET与 ContextRegistry.GetContext()..

您可以使用 lookup-method 替换方法,例如:

创建一个AbstractCommandFactory:

namespace MyNamespace {
  public abstract class AbstractCommandFactory : ICommandFactory {
    public abstract ICommand getMyCommand();  
  }
}

使用Spring.NET,你可以 getMyCommand 返回一个Spring.NET对象:

<objects>
  <object id="commandfactory"
          type="MyNamespace.AbstractCommandFactory, MyAssembly">
    <lookup-method name="getMyCommand" object="commands.mycommand" />
  </object>

  <object id="commands.mycommand" 
          type=MyNamespace.MyCommandImplementation, MyAssembly" />
</objects>

现在初始化Spring.NET应用程序上下文时,加载此命令工厂并传递引用。当您需要MyCommandImplementation的实例时,您只需从工厂实例请求一个:

public void doSomeWork() {
  // factory is an ICommandFactory
  // instantiated earlier using the explicit context.getObject("commandfactory")
  ICommand myCommand = this.factory.getMyCommand();
  myCommand.Execute();
}

现在,您对Spring.NET的显式依赖性非常小:仅在工厂的初始加载+实例化时。其余的代码保持干净。

奖励积分:您可以更轻松地创建ICommandFactory / ICommand模拟以对您的代码进行单元测试。