C# Unity依賴注入利用Attribute實現AOP功能


使用場景?

很多時候, 我們定義一個功能, 當我們要對這個功能進行擴展的時候, 按照常規的思路, 我們一般都是利用OOP的思想, 在原有的功能上進行擴展。

那么有沒有一種東西, 可以實現當我們需要擴展這個功能的時候, 在不修改原來的功能代碼的情況下實現, 這就是下面要說的到Unity。

 

1.准備工作

為項目添加NuGet包, 搜索Unity並且安裝。

在使用的項目中添加Unity的相關引用

using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.Unity;

 

2.假設場景

剛才上面說道, Unity可實現在不修改原功能的情況下, 添加額外的擴展功能。在我們的實際開發中, 也可以舉個簡單的例子。

當我們去做一個用戶注冊的功能, 最初的版本是完成了基本的注冊功能, 后來我們需要擴展了, 給他加上注冊校驗, 日志處理, 和異常捕捉的幾個功能, 那么接下來就演示, 如何用Unity給功能擴展。

 

 

3.如何使用

首先, 我們定義好一個最原始的注冊功能

        public static void Show()
        {
            User user = new User()
            {
                Name = "Eleven",
                Password = "123123123123"
            };
IUserProcessor porcessor = new UserProcessor();
            porcessor.RegUser(user); //簡單的用戶注冊
}

 

        public interface IUserProcessor
        {
            void RegUser(User user);
        }

        public class UserProcessor : IUserProcessor//MarshalByRefObject,
        {
            public void RegUser(User user)
            {
                Console.WriteLine("注冊");
            }
        }

 接下來, 我們要對這個注冊進行擴展了, 添加注冊校驗, 日志處理, 和異常捕捉的幾個功能。

1.先定義3個特性與對應的特性行為實現, 分別是注冊, 日志, 和異常。

       public class UserHandlerAttribute : HandlerAttribute  //注冊校驗
        {
            public override ICallHandler CreateHandler(IUnityContainer container)
            {
                ICallHandler handler = new UserHandler() { Order = this.Order };
                return handler;
            }
        }

        public class LogHandlerAttribute : HandlerAttribute   //日志處理
        {
            public override ICallHandler CreateHandler(IUnityContainer container)
            {
                return new LogHandler() { Order = this.Order };
            }
        }

        public class ExceptionHandlerAttribute : HandlerAttribute  //異常處理
        {
            public override ICallHandler CreateHandler(IUnityContainer container)
            {
                return new ExceptionHandler() { Order = this.Order };
            }
        }

  對應的每個特性的實現行為, 分別實現 注冊校驗, 日志記錄, 與 異常處理

        public class UserHandler : ICallHandler  //注冊校驗的行為
        {
            public int Order { get; set; }
            public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
            {
                User user = input.Inputs[0] as User;
                if (user.Password.Length < 10)
                {
                    return input.CreateExceptionMethodReturn(new Exception("密碼長度不能小於10位"));
                }
                Console.WriteLine("參數檢測無誤");
                
                IMethodReturn methodReturn = getNext.Invoke().Invoke(input, getNext);
                
                return methodReturn;
            }
        }

        public class LogHandler : ICallHandler    //日志處理的行為
        {
            public int Order { get; set; }
            public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
            {
                User user = input.Inputs[0] as User;
                string message = string.Format("RegUser:Username:{0},Password:{1}", user.Name, user.Password);
                Console.WriteLine("日志已記錄,Message:{0},Ctime:{1}", message, DateTime.Now);
                return getNext()(input, getNext);
            }
        }


        public class ExceptionHandler : ICallHandler   //異常處理的行為
        {
            public int Order { get; set; }
            public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
            {
                IMethodReturn methodReturn = getNext()(input, getNext);
                if (methodReturn.Exception == null)
                {
                    Console.WriteLine("無異常");
                }
                else
                {
                    Console.WriteLine("異常:{0}", methodReturn.Exception.Message);
                }
                return methodReturn;
            }
        }

按照現在思路, 我們要把這上面寫好的幾個功能添加在原來的注冊功能上, 首先, 我們回到最開始定義接口的地方, 給接口添加我們定義按的3個特性

        [UserHandlerAttribute(Order = 1)] //注冊校驗
        [LogHandlerAttribute(Order = 2)]  //日志處理
        [ExceptionHandlerAttribute(Order = 3)] //遺產處理
        public interface IUserProcessor
        {
            void RegUser(User user);
        }

//PS: 在上面的特性聲明中, 每個對應的Order 這個屬於排序, 相對於一個行為的執行順序, 這個內部是Unity的一個實現, 所以我們使用的過程中只需要聲明好標量即可。

然后, 我們在定義好的注冊方法中, 首先聲明一個Unity容器UnityContainer , 然后注冊其上面的接口 IUserProcessor, 最后調用其接口的注冊方法。

            //聲明一個容器
            IUnityContainer container = new UnityContainer();

            //聲明UnityContainer並注冊IUserProcessor
            container.RegisterType<IUserProcessor, UserProcessor>();

            container.AddNewExtension<Interception>().Configure<Interception>()
                .SetInterceptorFor<IUserProcessor>(new InterfaceInterceptor());
            IUserProcessor userprocessor = container.Resolve<IUserProcessor>();
            userprocessor.RegUser(user); //調用注冊方法。

 

最后, 我們看一下實際效果, 很輕松的實現了用於注冊時候擴展其他更多的行為

 

 

 

小結:

不難發現, Unity的實現 主要以在接口上定義的特性與實現行為  與其內部Unity容器的結合  實現的AOP功能。

因為上面是屬於靜態的寫法, 便於學習, 真正的實現AOP可動態配置, 在IOC里會有詳細的介紹。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM