AOP精简框架

  在我之前的文章<<用代理技术实现简单的AOP框架>>里介绍了用RealProxy来实现AOP的方法拦截,由于Realproxy的效率较低,且被拦截的对象必须继承自ContextBoundObject,所以其有自身的局限性.为了更高效和在实际项目具有更好的实用性,我用装饰器模式,以面向接口的方式设计了一个简单的AOP框架,并在我的项目里广泛地应用,取得不错的实践效果.
AOP框架只包含三个类:
Decorate,用来对原来对象的方法,事件进行拦截.
DecorateFactory,用来构造拦截器的对象链的工厂
DecoratorAttribute,用来对被拦截对象的类的施加拦截器标识.


三个类的实现为:

/*
 * Author      :Nathan.Liu
 * Unit        :Decorate.cs
 * CopyRights  :Nathan.Liu
 * Email       :candylyg@sina.com
 * Description :
 * Story       :
 *      2007/11/16 create by nathan
 */
using System;
using System.Collections.Generic;
using System.Text;
using LYG.Share.Interface;

namespace LYG.Share.AOP.Decorator
{
    public interface IDecorate<T>
    {
        void InitDecorator(T obj, IDictionary<string, object> context);
        T Decorator { get; }
        IDictionary<string, object> Context { get;}
    }

    public abstract  class Decorate<T> : IDecorate<T>
    {
        private IDictionary<string, object> _context;
        public IDictionary<string, object> Context
        {
            get { return _context; }
        }
        T _decorator;
        public T Decorator
        {
            get { return _decorator; }
        }
        public virtual  void InitDecorator(T obj, IDictionary<string, object> context)
        {
            _decorator = obj;
            _context = context;
            LoadDecorator();
        }
        public abstract void LoadDecorator();
    }
}

/*
 * Author      :Nathan.Liu
 * Unit        :DecorateFactory.cs
 * CopyRights  :Nathan.Liu
 * Email       :candylyg@sina.com
 * Description :
 * Story       :
 *      2007/11/16 create by nathan
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using LYG.Share.Interface;
using LYG.Share .Exceptions ;

namespace LYG.Share.AOP.Decorator
{   
    public sealed class DecorateFactory<T> where T:class
    {
        private IDictionary<string,Type>  _types;
        private T _sourceObject;
        public DecorateFactory(T sourceObject)
        {
            _types = new Dictionary<string,Type>();
            _sourceObject = sourceObject;
            foreach (DecoratorAttribute attr in sourceObject.GetType().GetCustomAttributes(true))
            {
                this.AddType(attr.TypeList);
            }
        }
        private void AddType(Type type)
        {
            _types[type.FullName] = type;
        }
        private void AddType(Type[] typeList)
        {
            foreach (Type type in typeList)
                this.AddType(type);
        }

        private  T BuildInstance()
        {
            T result = _sourceObject ;
            IDictionary<string, object> context = new Dictionary<string, object>();
            foreach ( KeyValuePair<string,Type> pair in _types )
            {
                object obj = Activator.CreateInstance(pair .Value);
                if (obj is T)
                {
                    if (obj is IDecorate<T>)
                    {
                        ((IDecorate<T>)obj).InitDecorator(result,context );
                    }
                    result = (T)obj;
                }
            }
            return result;
        }
        public static T CreateInstance(T SourceObject)
        {
            return new DecorateFactory<T>(SourceObject).BuildInstance();
        }
        public static T CreateInstance(Type type,params object[] args )
        {
            object obj = Activator.CreateInstance(type,args);
            if (obj is T)
            {
                T tObj = obj as T;
                return new DecorateFactory<T>(tObj).BuildInstance();
            }
            else
                throw new SBException ("invalid instance type");
        }
    }
}


/*
 * Author      :Nathan.Liu
 * Unit        :DecoratorAttribute.cs
 * CopyRights  :Nathan.Liu
 * Email       :candylyg@sina.com
 * Description :
 * Story       :
 *      2007/11/16 create by nathan
 */

using System;
using System.Collections.Generic;
using System.Text;

namespace LYG.Share.AOP.Decorator
{
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    public class DecoratorAttribute:Attribute
    {
        public DecoratorAttribute(params Type[] types)
        {
            _typeList = types;
        }
        private Type[] _typeList;
        public Type[] TypeList
        {
            get { return _typeList; }
        }
    }
}

测试用例代码:
  public interface ISample
    {
        string GO();
    }
    [DecoratorAttribute(typeof(Test), typeof(Test2))]
    public class Sample : ISample
    {
        public string GO()
        {
            return "GO GO GO";
        }
    }
    public class Test : Decorate<ISample>, ISample
    {
        public string GO()
        {
            return "before decorate " + Decorator.GO() + " after decorate";
        }
        public override  void LoadDecorator()
        {
        }
    }
    public class Test2 : Decorate<ISample>, ISample
    {
        public string GO()
        {
            return "First Decorate " + Decorator.GO() + " Last Decorate";
        }
        public override   void LoadDecorator()
        {
        }
    }
    public class TestCase
    {
        public string Test()
        {
            ISample tt = DecorateFactory<ISample>.CreateInstance(new Sample());
            return tt.GO();
        }
    }





此AOP框架的优点是在于其执行的高效性,几乎没有性能损耗,并且可以实现多重的拦截,其对方法和事件的拦截顺序取决于拦截器被DecorateAttribute标记的顺序.此框架要求每个被拦截的类和拦截实现同一个接口,并且每个拦截器都需要实现对接口中的每个方法一个至少形式上的拦截,我不知道这算不算是一个缺点.总之,我在项目中用得很爽.

posted @ 2007-12-20 00:51 Nathan.Liu 阅读(1933) 评论(11)  编辑 收藏 网摘 所属分类: AOPDesign Pattern

  回复  引用  查看    
#1楼 2007-12-20 07:48 | 菌哥      
学习!
  回复  引用  查看    
#2楼 2007-12-20 08:12 | 双鱼座      
包装一下接口方法也叫AOP?
  回复  引用  查看    
#3楼 2007-12-20 08:17 | Justin      
一会到公司再好好研究一下,先顶一下~
  回复  引用  查看    
#4楼 2007-12-20 08:38 | henry      
和本质上相反的aop要求的是
[DecoratorAttribute(typeof(Test), typeof(Test2))]
public class Sample : ISample
{
public string GO()
{
return "GO GO GO";
}
}
这东西本身应不作任何假设性描述,如果有新功能的切入你必须修改Sample 的attribute的代码显然违反aop原则,不过楼主改成XML方式描述相对而言好很多.看上面代码扩展部分对原对象方法的控制处理很有限
  回复  引用  查看    
#5楼 2007-12-20 08:45 | henry      
在我的框架中aop实现如下
[NClay.MVC.Controller]
class RoleHandler
{
public void Add(IRoleAdd logic);

public void Remove(IRoleRemove logic);

public void Load(IRoleLoad logic);

public void List(IRolesList logic);

public void UserAdd(IRoleUserAdd logic);

public void UserRemove(IRoleUserRemove logic);

public void UsersList(IRoleUsersList logic);

}
对以上所有方法aop接管如下
[NClay.MVC.ViewAspect(NClay.MVC.AspectLevel.High)]
public class Log:NClay.MVC.IAspect
{
#region IAspect Members

public void Aspect(object source, NClay.MVC.AspectHandler e)
{

Console.WriteLine(source.GetType() );
Console.WriteLine("\tBEGIN");
try
{
e.Execute(source);
Console.WriteLine("\t\tRun Succeeded");
}
catch (Exception e_)
{
Console.WriteLine( "\t\tRun Error");
Console.WriteLine("\t\t\t" + e_.Message);
}
Console.WriteLine("\tEND");
Console.WriteLine("");
}

#endregion
}
通过ViewAspect可以达到接管某种类型或某种类型的所有派生成员进行处理.
  回复  引用  查看    
#6楼 [楼主]2007-12-20 08:46 | Nathan.Liu      
henry:
如果有新功能的切入你必须修改Sample 的attribute的代码显然违反aop原则,

曾思考过这个问题,也曾想不对被拦截的对象有任何的修改.一直没有想到合适的办法,你提出的XML描述是个不错的想法,感谢的你的建议和文字
  回复  引用  查看    
#7楼 [楼主]2007-12-20 08:48 | Nathan.Liu      
henry:
可否提供e.Execute(source)的实现?
  回复  引用  查看    
#8楼 [楼主]2007-12-20 08:51 | Nathan.Liu      
henry:
public void Aspect(object source, NClay.MVC.AspectHandler e)
中是否以为对所有方法做同样的拦截处理?如果是,是否不具现实性?
  回复  引用  查看    
#9楼 2007-12-20 09:03 | henry      
@Nathan.Liu
抱赚源码不能提供,其实基础原理和的你实现一样都有一个容器统一接入处理.
有一点你会发现我所有方法的参数都是接口,如果方法的参数不是接口形式框架是不会处理的.
NClay.MVC.AspectHandler e这个是原方法执行的匿名函数句柄,这样用户在写功能切入时对原有方法执行的可控性非常高和灵活.

前面已经说了通过ViewAspect可以达到接管某种类型或某种类型的所有派生成员进行处理,这里的类型是指方法的参数类型

补上:框架aop的实现完全是针对业务逻辑处理所以其约束性也很明显,必须按框架的规则进行开发.
  回复  引用  查看    
#10楼 2007-12-20 10:30 | 代码乱了      
似乎不能对调用方法的参数拦截处理
  回复  引用    
#11楼 2008-07-19 22:10 | dw [未注册用户]
不错不错,老刘同志,茫茫网海也遇到你,太神了!

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-12-20 00:59 编辑过
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》



相关文章:

相关链接: