很早就注意到AOP将带来一些新的气象,不过AOP的一些思想在.NET里应该是有体现的.如果你做过ASP.NET的filter过滤,可能就会比较容易理解了.
和以往一样,我这不过多谈理论,你可以随便找到一把文章.
接下来的例子可以下载:
https://files.cnblogs.com/QPG2006/AopDemo.rar
没有把它集成到GPG_Demo方案中是避免影响其他例子的效果,下面开始吹牛了,请打起精神.
AOP是想有更加省事省时的办法现有操作扩展一些行为,常见的是日志操作和权限判断.
当然你也可以手工在那些需要的调用前执行加入扩展行为,只是确实挺麻烦的.
我们下面的例子有两个意图:
1) 对所有方法和属性设置进行日志操作
2) 只允许经理去调整产品的价格
下面的例子是演示如何利用Castle.DynamicProxy来实现,实际应用就比较麻烦,但是能说明思路.
你可以执行Step1下的测试来看看结果.代码如下:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
namespace Castle.AopDemo
{
using System;
using NUnit.Framework;
![](/Images/OutliningIndicators/InBlock.gif)
using Castle.DynamicProxy;
![](/Images/OutliningIndicators/InBlock.gif)
using Castle.AopDemo.Components;
using Castle.AopDemo.Interceptors;
using Castle.AopDemo.Mixins;
[TestFixture]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public class Tester
{
private ProxyGenerator _generator;
![](/Images/OutliningIndicators/InBlock.gif)
[SetUp]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void Init()
{
_generator = new ProxyGenerator();
}
![](/Images/OutliningIndicators/InBlock.gif)
[TearDown]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void Finish()
{
}
![](/Images/OutliningIndicators/InBlock.gif)
[Test]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void testLog()
{
object productProxy = _generator.CreateClassProxy(
typeof(Product), new LoggerInterceptor() );
![](/Images/OutliningIndicators/InBlock.gif)
Assert.IsTrue( typeof(Product).IsAssignableFrom( productProxy.GetType() ) );
![](/Images/OutliningIndicators/InBlock.gif)
Product p = productProxy as Product;
Assert.AreEqual(0,p.Price);
p.setPrice(100);
//p.outStock(2);
Assert.AreEqual(100,p.Price);
![](/Images/OutliningIndicators/InBlock.gif)
}
[Test]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void testSecurity()
{
GeneratorContext context = new GeneratorContext();
SecurityMixin mixin_instance = new SecurityMixin(Role.Manager);
context.AddMixinInstance( mixin_instance );
![](/Images/OutliningIndicators/InBlock.gif)
SecurityCheckInterceptor interceptor = new SecurityCheckInterceptor();
![](/Images/OutliningIndicators/InBlock.gif)
object proxy = _generator.CreateCustomClassProxy(
typeof(Product), interceptor, context );
Product p = proxy as Product;
p.setPrice(100);
Assert.AreEqual(100,p.Price);
}
[Test]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void SimpleMixin()
{
GeneratorContext context = new GeneratorContext();
SecurityMixin mixin_instance = new SecurityMixin(Role.Employee);
context.AddMixinInstance( mixin_instance );
![](/Images/OutliningIndicators/InBlock.gif)
AssertInvocationInterceptor interceptor = new AssertInvocationInterceptor();
![](/Images/OutliningIndicators/InBlock.gif)
object proxy = _generator.CreateCustomClassProxy(
typeof(Product), interceptor, context );
Assert.IsNotNull(proxy);
Assert.IsTrue( typeof(Product).IsAssignableFrom( proxy.GetType() ) );
![](/Images/OutliningIndicators/InBlock.gif)
Assert.IsFalse( interceptor.Invoked );
![](/Images/OutliningIndicators/InBlock.gif)
ISecurity mixin = proxy as ISecurity;
Assert.IsNotNull(mixin);
Assert.AreEqual(Role.Employee, mixin.getRole());
![](/Images/OutliningIndicators/InBlock.gif)
Assert.IsTrue( interceptor.Invoked );
Assert.AreSame( proxy, interceptor.proxy );
Assert.AreSame( mixin_instance, interceptor.mixin );
}
![](/Images/OutliningIndicators/InBlock.gif)
}
}
![](/Images/OutliningIndicators/None.gif)
如果在真的项目里使用,采用castle集成的Aspect#会好些,你要配置如下的文件(在step2项目里有):
<?xml version="1.0" encoding="utf-8" ?>
![](/Images/OutliningIndicators/None.gif)
<configuration>
<components>
<component id="salemgr" type="Castle.AopDemo.Components.SaleMgr, AOP">
<parameters>
<Role>Role.Manager</Role>
</parameters>
</component>
<component id="product" type="Castle.AopDemo.Components.Product, AOP">
<parameters>
<name>P1</name>
<price>100</price>
<num>5</num>
</parameters>
</component>
</components>
<facilities>
<facility id="aspectsharp" type="Castle.Facilities.AspectSharp.AspectSharpFacility,Castle.Facilities.AspectSharp">
<![CDATA[
import Castle.AopDemo.Components in AOP
![](/Images/OutliningIndicators/None.gif)
import Castle.AopDemo.Mixins in AOP
![](/Images/OutliningIndicators/None.gif)
import Castle.AopDemo.Interceptors in AOP
![](/Images/OutliningIndicators/None.gif)
aspect LogForProperty for [Castle.AopDemo.Components]
include SecurityMixin
pointcut propertywrite|method(*)
advice(Castle.AopDemo.Interceptors.LoggerInterceptor)
end
end
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
]]>
</facility>
</facilities>
</configuration> 下面是演示片断:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
namespace Castle.AopDemo
{
using System;
using NUnit.Framework;
![](/Images/OutliningIndicators/InBlock.gif)
using Castle.Model.Configuration;
![](/Images/OutliningIndicators/InBlock.gif)
using Castle.Windsor;
![](/Images/OutliningIndicators/InBlock.gif)
using Castle.MicroKernel.SubSystems.Configuration;
![](/Images/OutliningIndicators/InBlock.gif)
using Castle.AopDemo.Components;
using Castle.AopDemo.Interceptors;
using Castle.Facilities.AspectSharp;
[TestFixture]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public class Tester
{
IWindsorContainer container;
[SetUp]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void Init()
{
container = new WindsorContainer(@"../../AppConfig.config");
}
![](/Images/OutliningIndicators/InBlock.gif)
[TearDown]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void Finish()
{
container.Dispose();
}
![](/Images/OutliningIndicators/InBlock.gif)
[Test]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void testOK()
{
Product p=container["product"] as Product;
SaleMgr s=container["salemgr"] as SaleMgr;
Assert.AreEqual(100,p.Price);
Assert.AreEqual(5,p.Stocks);
Assert.AreEqual(Role.Other,s.CurUserRole);
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
s.CurUserRole=Role.Manager;
Console.WriteLine("----------------------------------------");
s.adjustPrice(p,200);
Console.WriteLine("----------------------------------------");
Assert.AreEqual(200,p.Price);
s.CurUserRole=Role.Employee;
s.acceptOrder(p,2);
Console.WriteLine("----------------------------------------");
Assert.AreEqual(3,p.Stocks);
}
![](/Images/OutliningIndicators/InBlock.gif)
[Test]
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void testException()
{
Product p=container["product"] as Product;
SaleMgr s=container["salemgr"] as SaleMgr;
s.adjustPrice(p,200);
}
}
}
![](/Images/OutliningIndicators/None.gif)
限于篇幅,还是请有兴趣的读者下载示例看效果吧,我就不截图了。