技术篇(6)--大话AOP

很早就注意到AOP将带来一些新的气象,不过AOP的一些思想在.NET里应该是有体现的.如果你做过ASP.NET的filter过滤,可能就会比较容易理解了.

和以往一样,我这不过多谈理论,你可以随便找到一把文章.
接下来的例子可以下载:
https://files.cnblogs.com/QPG2006/AopDemo.rar

没有把它集成到GPG_Demo方案中是避免影响其他例子的效果,下面开始吹牛了,请打起精神.

AOP是想有更加省事省时的办法现有操作扩展一些行为,常见的是日志操作和权限判断.
当然你也可以手工在那些需要的调用前执行加入扩展行为,只是确实挺麻烦的.

我们下面的例子有两个意图:
1) 对所有方法和属性设置进行日志操作
2) 只允许经理去调整产品的价格

下面的例子是演示如何利用Castle.DynamicProxy来实现,实际应用就比较麻烦,但是能说明思路.
你可以执行Step1下的测试来看看结果.代码如下:

namespace  Castle.AopDemo {
    
using System;
    
using NUnit.Framework;

    
using Castle.DynamicProxy;

using Castle.AopDemo.Components;
using    Castle.AopDemo.Interceptors;
using    Castle.AopDemo.Mixins;
    [TestFixture]
    
public class Tester {
    
        
private ProxyGenerator _generator;

        [SetUp]
        
public void Init() {
            _generator 
= new ProxyGenerator();
        }


        [TearDown]
        
public void Finish() {
            
        }


        [Test]
        
public void testLog() {
            
object productProxy = _generator.CreateClassProxy( 
                
typeof(Product), new LoggerInterceptor() );

            Assert.IsTrue( 
typeof(Product).IsAssignableFrom( productProxy.GetType() ) );

            Product p 
= productProxy as Product;
            Assert.AreEqual(
0,p.Price);
            p.setPrice(
100);
            
//p.outStock(2);
            Assert.AreEqual(100,p.Price);
            
        
        

        }
    
        
            [Test]
        
public void testSecurity() {
            GeneratorContext context 
= new GeneratorContext();
            SecurityMixin mixin_instance 
= new SecurityMixin(Role.Manager);
            context.AddMixinInstance( mixin_instance );

            SecurityCheckInterceptor interceptor 
= new SecurityCheckInterceptor();

            
object proxy = _generator.CreateCustomClassProxy( 
                
typeof(Product), interceptor, context );
            
            Product p 
= proxy as Product;
            
            p.setPrice(
100);
            Assert.AreEqual(
100,p.Price);
        }

        [Test]
        
public void SimpleMixin() {
            GeneratorContext context 
= new GeneratorContext();
            SecurityMixin mixin_instance 
= new SecurityMixin(Role.Employee);
            context.AddMixinInstance( mixin_instance );

            AssertInvocationInterceptor interceptor 
= new AssertInvocationInterceptor();

            
object proxy = _generator.CreateCustomClassProxy( 
                
typeof(Product), interceptor, context );
            
            Assert.IsNotNull(proxy);
            Assert.IsTrue( 
typeof(Product).IsAssignableFrom( proxy.GetType() ) );

            Assert.IsFalse( interceptor.Invoked );

            ISecurity mixin 
= proxy as ISecurity;
            Assert.IsNotNull(mixin);
            Assert.AreEqual(Role.Employee, mixin.getRole());

            Assert.IsTrue( interceptor.Invoked );
            Assert.AreSame( proxy, interceptor.proxy );
            Assert.AreSame( mixin_instance, interceptor.mixin );
        }


    }

}

如果在真的项目里使用,采用castle集成的Aspect#会好些,你要配置如下的文件(在step2项目里有):
<?xml version="1.0" encoding="utf-8" ?> 

<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

import Castle.AopDemo.Mixins 
in AOP

import Castle.AopDemo.Interceptors 
in AOP

aspect LogForProperty 
for [Castle.AopDemo.Components]
  include SecurityMixin 
  pointcut propertywrite
|method(*)
    advice(Castle.AopDemo.Interceptors.LoggerInterceptor) 
   
  end 
end 


]]
> 
        
</facility> 
    
</facilities> 
</configuration> 

下面是演示片断:
namespace  Castle.AopDemo {
    
using System;
    
using NUnit.Framework;

    
using Castle.Model.Configuration;

    
using Castle.Windsor;

    
using Castle.MicroKernel.SubSystems.Configuration;

    
using Castle.AopDemo.Components;
    
using Castle.AopDemo.Interceptors;
    
using Castle.Facilities.AspectSharp;
    
    [TestFixture]
    
public class Tester {
        IWindsorContainer container;
    
        [SetUp]
        
public void Init() {
            container 
= new WindsorContainer(@"../../AppConfig.config");
                
        }


        [TearDown]
        
public void Finish() {
            container.Dispose();
        }


        [Test]
        
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);
        


            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);
        }
    

        [Test]
        
public void testException() {
            Product p
=container["product"as Product;
            SaleMgr s
=container["salemgr"as SaleMgr;
                
            s.adjustPrice(p,
200);
        
        }
    
    }

}

限于篇幅,还是请有兴趣的读者下载示例看效果吧,我就不截图了。


posted @ 2005-10-14 18:23  成为-行动-拥有(BeDoHave)  阅读(1413)  评论(2编辑  收藏  举报