中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

Lind.DDD.Aspects通過Plugins實現方法的動態攔(lan)截~Lind里的AOP

回到目錄

.Net MVC之(zhi)(zhi)所以發展的(de)(de)如些之(zhi)(zhi)好,一個很重要原因就是它公(gong)開了一組AOP的(de)(de)過濾器,即使用(yong)這些過濾器可(ke)以方便的(de)(de)攔截(jie)controller里的(de)(de)action,并注(zhu)入我們自己的(de)(de)代碼邏輯(ji),向全局的(de)(de)異常記錄(lu),用(yong)戶(hu)授(shou)權(quan)(quan),Url授(shou)權(quan)(quan),操作(zuo)行為記錄(lu)等,這一大批Lind的(de)(de)基本組件都是實(shi)現MVC和API的(de)(de)過濾實(shi)現的(de)(de),使用(yong)這些過濾讓我們不(bu)用(yong)去像(xiang)HttpModule和HttpHandler那樣,還要在Config里配置注(zhu)入點,讓程(cheng)序(xu)員在開發方式上感覺(jue)很舒服,維護成功很低!

本文主要內容點

  1. Lind.DDD里的方法攔截器
  2. 動態注入需要Lind.DDD.Plugins的支持
  3. 零配置的方法攔截
  4. 一個日志攔截器
  5. 正在構建一個緩存攔截器

目錄結構

 

Lind.DDD里的方法攔截器

Lind.DDD.Aspects這個攔截器起源自ABP框架,但不知道為什么,ABP對這個攔截器并沒有完全實現,所以今天大叔又實現了一下,解決了相關BUG, 對方法攔截上,在動態代理工廠里對方法攔截(jie)上下文(wen)添加了一些必要的(de)參數,因(yin)為大叔認為,你只提供一個“方法名稱”參數,太過簡單(dan)了,哈哈。

    /// <summary>
    /// 方法(fa)相關(guan)信息
    /// </summary>
    public class MethodMetadata
    {
        /// <summary>
        /// 上下文(wen)
        /// </summary>
        private MethodInfo _context;
        /// <summary>
        /// 方(fang)法名
        /// </summary>
        private string _methodName;

        public MethodMetadata(string methodName, MethodInfo context = null)
        {
            _methodName = methodName;
            _context = context;
        }
        /// <summary>
        /// 方法名(ming)稱
        /// </summary>
        public virtual string MethodName
        {
            get { return _methodName; }
            set { _methodName = value; }
        }
        /// <summary>
        /// 方(fang)法上下(xia)文(wen)
        /// </summary>
        public virtual string Context
        {
            get { return _context; }
            set { _context = value; }
        }
    }

一個簡單的日志攔截器的實現,它(ta)在方(fang)法執行前去攔截

   /// <summary>
    /// 方法執行前攔截(jie),并記錄日志
    /// </summary>
    public class LoggerAspectAttribute : BeforeAspectAttribute
    {
        public override void Action(InvokeContext context)
        {
            Console.WriteLine("logger start!" + context.Method.MethodName);
            Lind.DDD.Logger.LoggerFactory.Instance.Logger_Info(context.Method.MethodName + "這個(ge)方法開始執行");
        }
    }

而(er)在程序中,這(zhe)(zhe)個特性Attribute如何被動態代理攔截(jie)呢,事件上,如果你直接寫代碼(ma)也是(shi)(shi)可(ke)以的(de),就是(shi)(shi)使用(yong)Aspect提供(gong)的(de)ProxyFactory工廠來進行生產(chan),但大叔認為,這(zhe)(zhe)樣的(de)代碼(ma)耦合度太高,而(er)且對于(yu)現有(you)的(de)代碼(ma)還需要進行修(xiu)改,最(zui)重(zhong)要一點(dian),這(zhe)(zhe)種代碼(ma)總感覺有(you)種壞味(wei)道(dao)!

     static void Main(string[] args)
        {
            ProxyFactory.CreateProxy<ITest>(typeof(LoggerAspectTest)).Do();
            Console.Read();
        }

所(suo)以就有了下(xia)面大叔的(de)封(feng)裝,用(yong)到了Lind.DDD.Plugins這(zhe)(zhe)個插件模式,將所(suo)有的(de)攔(lan)截器都先進行注冊,然后在生產對(dui)象(xiang)時為(wei)它(ta)動態(tai)添(tian)加對(dui)應的(de)ProxyFactory對(dui)象(xiang),請大家(jia)接著向(xiang)下(xia)看,動態(tai)注入需要Lind.DDD.Plugins的(de)支持這(zhe)(zhe)部分講解(jie)。

動態注入需要Lind.DDD.Plugins的支持

上面的攔截器只是簡單的實現,簡單的調用,而不具有一般性,即你需要自己維護需要“攔截的代碼”,而大叔在進行使用中感覺很不爽,于是想起了Plugins,讓插件為我們實現這種注入,就像MVC的Filter一樣,在框(kuang)架本身去實現方(fang)法(fa)攔截的功能!大叔認為這樣(yang)才是最好的!

1 所(suo)有攔(lan)截器都(dou)繼承(cheng)(cheng)IAspectProxy表示(shi)接口,而它自己(ji)則(ze)是繼承(cheng)(cheng)IPlugins的(de)

 

   /// <summary>
    /// 支(zhi)持AOP攔截的(de)接(jie)口,它被(bei)認為是一種插件動(dong)態注入(ru)到系統中
    /// </summary>
    public interface IAspectProxy : Lind.DDD.Plugins.IPlugins { }

 

2 在PluginManager的Resolve方法中(zhong),添加動態的ProxyFactory實(shi)現(xian),讓(rang)實(shi)現(xian)了IAspectProxy的類型,自動進行攔(lan)截器(qi)的實(shi)現(xian)

      /// <summary>
        /// 從(cong)插件容器(qi)里返回對象
        /// </summary>
        /// <param name="serviceName">對(dui)象全名(ming)</param>
        /// <param name="serviceType">接口類型</param>
        /// <returns></returns>
        public static object Resolve(string serviceName, Type serviceType)
        {
            var obj = _container.ResolveNamed(serviceName, serviceType);
            if (typeof(Lind.DDD.Aspects.IAspectProxy).IsAssignableFrom(serviceType))
            {
                obj = ProxyFactory.CreateProxy(serviceType, obj.GetType());
            }
            return obj;
        }

OK,有了(le)上面(mian)的(de)代碼,我們(men)的(de)方(fang)法攔截就成了(le)一種插件(jian)了(le),在使用(yong)的(de)時間之(zhi)前的(de)插件(jian)的(de)使用(yong)方(fang)法相同,當然底層(ceng)還是使用(yong)autofac來實(shi)現的(de)Ioc容器。

 var old = Lind.DDD.Plugins.PluginManager.Resolve<IAopHelloTest2>("Lind.DDD.UnitTest.AopHello");
 old.Hello("zz", 1);

一個日志攔截器

日(ri)志(zhi)記錄是一些業務(wu)復雜方法(fa)必備的,如一些訂單方法(fa),用(yong)戶(hu)提現(xian)方法(fa)都會添(tian)加相(xiang)關(guan)的日(ri)志(zhi),而如果(guo)希望動態添(tian)加日(ri)志(zhi),而不在代碼段中(zhong)去添(tian)加,則可(ke)以設計一個日(ri)志(zhi)攔(lan)截器,當然你可(ke)以在方法(fa)執(zhi)行(xing)前去控(kong)制,也(ye)可(ke)以在方法(fa)執(zhi)行(xing)后去控(kong)制!

  /// <summary>
    /// 方法執行前攔截(jie),并記錄日志
    /// </summary>
    public class LoggerAspectAttribute : BeforeAspectAttribute
    {
        public override void Action(InvokeContext context)
        {
            Console.WriteLine("logger start!" + context.Method.MethodName);
            Lind.DDD.Logger.LoggerFactory.Instance.Logger_Info(context.Method.MethodName + "這個方法開始執行");
        }
    }

    /// <summary>
    /// 方(fang)法執(zhi)行完成后攔截,并記錄(lu)日志
    /// </summary>
    public class LoggerEndAspectAttribute : AfterAspectAttribute
    {
        public override void Action(InvokeContext context)
        {
            Console.WriteLine("logger start!" + context.Method.MethodName);
            Lind.DDD.Logger.LoggerFactory.Instance.Logger_Info(context.Method.MethodName + "這個方法開(kai)始執行");
        }
    }

目錄方(fang)法(fa)需要(yao)(yao)添(tian)加(jia)這種日(ri)志的行為,只要(yao)(yao)在方(fang)法(fa)上添(tian)加(jia)對(dui)應的特性(xing)即可(ke),(方(fang)法(fa)不(bu)需要(yao)(yao)為虛方(fang)法(fa))而(er)不(bu)需要(yao)(yao)修改方(fang)法(fa)代(dai)碼體(ti),如下面的代(dai)碼

   /// <summary>
    /// AOP調(diao)用方式
    /// </summary>
    public class LoggerAspectTest : ITest
    {
        [LoggerAspectAttribute]
        public void Do()
        {
            //我(wo)做事情
            Console.WriteLine("我做事情");
        }
    }

正在構建一(yi)個緩存攔截(jie)器

目前,大叔(shu)(shu)正在(zai)構建一個緩存(cun)的(de)(de)攔截器,主(zhu)要是(shi)(shi)實(shi)現對方法返回值的(de)(de)緩存(cun),而不(bu)需要將這種緩存(cun)判斷(duan)的(de)(de)邏輯寫在(zai)每(mei)個方法體內,大叔(shu)(shu)認為,這種面向切(qie)面的(de)(de)AOP的(de)(de)設計,才(cai)是(shi)(shi)大勢(shi)所趨(qu),敬請大家期待!

   /// <summary>
    /// 緩存攔截(jie)器(qi)
    /// </summary>
    public class CachingAspectAttribute : BeforeAspectAttribute
    {
        CachingMethod cachingMethod;
        public CachingAspectAttribute(CachingMethod cachingMethod)
        {
            this.cachingMethod = cachingMethod;
        }

        public override void Action(InvokeContext context)
        {
            var method = context.Method;
            string prefix = "Lind";
            var baseInterfaces = context.GetType().GetInterfaces();
            if (baseInterfaces != null && baseInterfaces.Any())
            {
                foreach (var item in baseInterfaces)
                {
                    prefix += item.ToString() + "_";
                }
            }

            //鍵名(ming),在put和get時使用(yong)
            var key = prefix + method.MethodName;
            Console.WriteLine(key);
            switch (cachingMethod)
            {
                case CachingMethod.Remove:
                    //……
                    break;
                case CachingMethod.Get:
                    //……
                    break;
                case CachingMethod.Put:
                    //……
                    break;
                default:
                    throw new InvalidOperationException("無效的(de)緩(huan)存方式。");

            }
        }
    }

我(wo)們對支(zhi)持的(de)追求將不會停(ting)止,希望廣(guang)大青年都可(ke)以踏一(yi)(yi)心來,去認真(zhen)的(de)研究一(yi)(yi)個技術,事實上,對一(yi)(yi)個技術研究透了,大叔(shu)認為(wei)就足夠了!

此致

敬禮

回到目錄

 

posted @ 2016-12-06 22:14  張占嶺  閱讀(978)  評論(0)    收藏  舉報