Autofac整合Castle.DynamicProxy实现AOP
1.官网的例子有一些问题。自己学习总结下并且重新打包一个版本供学习。
1.AttributedInterfaceInterceptionFixture
[TestFixture] public class AttributedInterfaceInterceptionFixture { [Intercept(typeof(AddOneInterceptor))] public interface IHasI { int GetI(); } public class C : IHasI { public int I { get; private set; } public C() { I = 10; } public int GetI() { return I; } } class AddOneInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { invocation.Proceed(); if (invocation.Method.Name == "GetI") invocation.ReturnValue = 1 + (int)invocation.ReturnValue; } } [Test] public void DetectsNonInterfaceServices() { var builder = new ContainerBuilder(); builder.RegisterType<C>().EnableInterfaceInterceptors(); builder.RegisterType<AddOneInterceptor>(); var c = builder.Build(); var dx = Assert.Throws<DependencyResolutionException>(() => c.Resolve<C>()); Assert.IsInstanceOf<InvalidOperationException>(dx.InnerException); } [Test] public void FindsInterceptionAttributeOnReflectionComponent() { var builder = new ContainerBuilder(); builder.RegisterType<C>().As<IHasI>().EnableInterfaceInterceptors(); builder.RegisterType<AddOneInterceptor>(); var cpt = builder.Build().Resolve<IHasI>(); Assert.AreEqual(11, cpt.GetI()); // proxied } [Test] public void FindsInterceptionAttributeOnExpressionComponent() { var builder = new ContainerBuilder(); builder.Register(c => new C()).As<IHasI>().EnableInterfaceInterceptors(); builder.RegisterType<AddOneInterceptor>(); var cpt = builder.Build().Resolve<IHasI>(); Assert.AreEqual(11, cpt.GetI()); // proxied } }
2.ClassInterceptorsFixture
[TestFixture] public class ClassInterceptorsFixture { [Intercept(typeof(AddOneInterceptor))] public class C { public int I { get; set; } public C(int i) { I = i; } public virtual int GetI() { return I; } } class AddOneInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { invocation.Proceed(); if (invocation.Method.Name == "GetI") invocation.ReturnValue = 1 + (int)invocation.ReturnValue; } } [Test] public void InterceptsReflectionBasedComponent() { var builder = new ContainerBuilder(); builder.RegisterType<C>().EnableClassInterceptors(); builder.RegisterType<AddOneInterceptor>(); var container = builder.Build(); var i = 10; var c = container.Resolve<C>(TypedParameter.From(i)); var got = c.GetI(); Assert.AreEqual(i + 1, got); } }
3.InterceptorsChosenByMetadataFixture
[TestFixture] public class InterceptorsChosenByMetadataFixture { public interface ICustomerService { int GetVisitCount(); } public class CustomerService : ICustomerService { int VisitCount { get; set; } public CustomerService() { VisitCount = 10; } public int GetVisitCount() { return VisitCount; } } class AddOneInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { invocation.Proceed(); if (invocation.Method.Name.StartsWith("Get")) invocation.ReturnValue = 1 + (int)invocation.ReturnValue; } } [Test] public void InterceptsWhenUsingExtendedPropertyAndType() { var builder = new ContainerBuilder(); builder.RegisterType<CustomerService>() .As<ICustomerService>() .EnableInterfaceInterceptors() .InterceptedBy(typeof(AddOneInterceptor)); builder.RegisterType<AddOneInterceptor>(); var container = builder.Build(); var cs = container.Resolve<ICustomerService>(); Assert.AreEqual(11, cs.GetVisitCount()); } }
4.InterfaceInterceptorsFixture
[TestFixture] public class InterfaceInterceptorsFixture { [Test(Description = "Interception should not be able to occur against internal interfaces.")] public void DoesNotInterceptInternalInterfaces() { // DynamicProxy2 only supports visible interfaces so internal won't work. var builder = new ContainerBuilder(); builder.RegisterType<StringMethodInterceptor>(); builder .RegisterType<Interceptable>() .EnableInterfaceInterceptors() .InterceptedBy(typeof(StringMethodInterceptor)) .As<IInternalInterface>(); var container = builder.Build(); var dre = Assert.Throws<DependencyResolutionException>(() => container.Resolve<IInternalInterface>()); Assert.IsInstanceOf<InvalidOperationException>(dre.InnerException, "The inner exception should explain about public interfaces being required."); } [Test(Description = "Interception should be able to occur against public interfaces.")] public void InterceptsPublicInterfaces() { var builder = new ContainerBuilder(); builder.RegisterType<StringMethodInterceptor>(); builder .RegisterType<Interceptable>() .EnableInterfaceInterceptors() .InterceptedBy(typeof(StringMethodInterceptor)) .As<IPublicInterface>(); var container = builder.Build(); var obj = container.Resolve<IPublicInterface>(); Assert.AreEqual("intercepted-PublicMethod", obj.PublicMethod(), "The interface method should have been intercepted."); } public class Interceptable : IPublicInterface, IInternalInterface { public string PublicMethod() { throw new NotImplementedException(); } public string InternalMethod() { throw new NotImplementedException(); } } public interface IPublicInterface { string PublicMethod(); } internal interface IInternalInterface { string InternalMethod(); } private class StringMethodInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { if (invocation.Method.ReturnType == typeof(string)) { invocation.ReturnValue = "intercepted-" + invocation.Method.Name; } else { invocation.Proceed(); } } } }
代码下载: AopDemo
总结: 相对于spring.net繁琐的API和大量XML, Autofac&DynamicProxy 提供了又一种轻量级IOC&AOP解决方案。要说不足的地方。 与当前主流技术(如WCF,MVC,ORM)整合稍弱一些(也有可能可以很好整合,只是官方Demo没有给出。需要进一步去学习)。。