我目前正在尝试使用Castle实现AOP。我创建了一个处理业务的.NET解决方案(让我们将其命名为Project 1)。我正在考虑创建一个单独的项目,它将容纳我所有与AOP相关的类(方面)(这被命名为Project 2)。我的问题是:
1)是否可以在Project 1中使用xml配置文件来配置在运行时应用哪些方面? (我对这种可能性有一个很好的想法,但如果不然,请告诉我)
2)是否有可能不接触项目1(代码更改/重建)以添加新方面/删除旧方面并通过项目2管理所有这些?换句话说,由于未来添加或删除方面,我不想更改/构建我的业务解决方案。
答案 0 :(得分:1)
您可以使用XML(https://github.com/castleproject/Windsor/blob/master/docs/registering-components.md)配置组件,这不需要重建,项目2也可以配置AOP,您可以让项目1调用项目2来注册IOC服务,从这一点开始,您可以注册拦截器作为方面并将它们应用于您希望的任何组件,项目2将需要引用项目1或包含您希望为其注册的接口和实现的项目。
示例:
container.Register(
Component.For<LoggingInterceptor>().Lifestyle.Transient,
Component.For<CacheInterceptor>().Lifestyle.Transient,
Component.For<IOrderRepository>().ImplementedBy<OrderRepository>());
您不必更改业务代码,您可以按正确方式注册拦截器,在项目2中,您将引用业务项目并针对该接口注册任何自定义拦截器。您可以完全避免xml配置并在项目2中执行,您将重建项目2将其放入,然后重新启动应用程序。你也可以用xml注册拦截器(https://github.com/castleproject/Windsor/blob/master/docs/xml-registration-reference.md)
请参阅https://github.com/castleproject/Windsor/blob/master/docs/registering-components.md中的拦截器和代理组件部分,了解拦截器的xml configuratino。
所以例如:
控制台应用项目(参考aop和业务项目)
static void Main(string[] args)
{
var container = IocContainerFactory.GetContainer();
ISomeBusinessService service = container.Kernel.Resolve<ISomeBusinessService>();
Console.WriteLine(service.ReturnSomething());
Console.ReadLine();
}
商业项目
public interface ISomeBusinessService
{
string ReturnSomething();
}
public class SomeBusinessService : ISomeBusinessService
{
public string ReturnSomething()
{
return "some business value from service";
}
}
AOP项目(参考业务项目)
public static class IocContainerFactory
{
public static IWindsorContainer GetContainer()
{
var container = new WindsorContainer();
container.Register(Component.For<IInterceptor>().ImplementedBy<TraceLoggingInterceptor>().LifestyleTransient());
container.Register(Component.For<ISomeBusinessService>().ImplementedBy<SomeBusinessService>().LifestyleTransient().Interceptors<TraceLoggingInterceptor>());
return container;
}
}
public class TraceLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("{0} - {1}", invocation.TargetType, invocation.Method);
invocation.Proceed();
}
}