几个月前我发现了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,他们只是想补充它的功能。我需要完全更换。
答案 0 :(得分:9)
简而言之,是的,Spring.Net AOP可以按照您使用基于XML的配置描述的方式工作:您不必使用那些最初的两行代码,实际上不鼓励使用基于代码的配置。您可以仅使用基于XML的配置来配置Spring.Net AOP,这实际上是推荐的方法。
有几个步骤:
示例配置(从实时配置推广):
<!-- 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模拟以对您的代码进行单元测试。