IOC與DI+面向切面編程AOP

IOC與DI

1 IOC控制反轉和DI依賴注入

1.1 定義及作用

DIP 依賴倒置原則:系統架構時,高層模塊不應該依賴低模塊,二者通過抽象來依賴
依賴抽象而不是細節

貫徹依賴倒置原則,左邊能抽象,右邊實例化的時候不能直接用抽象,所以需要藉助第三方
高層本來是依賴低層,但是可以通過工廠(容器)來決定細節,去掉對低層的依賴。

IOC(Inversion of Control)控制反轉:把高層對低層的依賴,轉移到第三方決定,避免高層的直接依賴,那麼程序架構就具備良好的擴展性和穩定性

DI(Dependency Injection) 依賴注入:是用來實現IOC的一種手段
在構造對象時,可以自動化的取初始化,對象需要的其他對象(構造函數注入、屬性注入、方法注入)
不管是什麼注入,都是通過反射來實現的

有了依賴注入,才能做到無限層級的依賴抽象,才能做到控制反轉

1.2 分層的意義

分層是必須的
爲什麼分層:
1、職責清晰,方便分工合作
2、代碼複用
3、體積小、方便維護

2 Unity的使用

2.1 安裝

  1. install-package Unity
  2. install-package Unity.Interception
  3. install-package Unity.Interception.Configuration

2.2 Unity容器初步運用

//1、聲明一個容器
IUnityContainer container = new UnityContainer();
//2、初始化容器,註冊類型
container.RegisterType<IPhone, AndroidPhone>();

//3、創建對象,通過反射實現
IPhone phone = container.Resolve<IPhone>();
phone.Call();

2.3 Unity多種註冊,一對多的註冊

//1、聲明一個容器
IUnityContainer container = new UnityContainer();
//2、初始化容器,註冊類型
container.RegisterType<IPhone, AndroidPhone>();//接口


container.RegisterType<ApplePad, ApplePadChild>();//父子類

//container.RegisterType<AbstractPad, ApplePad>();//抽象類和子類
//container.RegisterType<AbstractPad, ApplePadChild>();//會覆蓋 要想不被覆蓋 傳入形參


container.RegisterType<AbstractPad, ApplePad>("child");//抽象類和子類  一對多
container.RegisterType<AbstractPad, ApplePadChild>("GrandChild");

container.RegisterInstance<ITV>(new AppleTV(123));//註冊實例,不常用(因爲依賴細節了)

//3、創建對象,通過反射實現
IPhone phone = container.Resolve<IPhone>();
phone.Call();

//AbstractPad pad = container.Resolve<AbstractPad>();
ApplePad applePad = container.Resolve<ApplePad>();

AbstractPad childPad = container.Resolve<AbstractPad>("child");
childPad.Show();
AbstractPad GrandChildPad = container.Resolve<AbstractPad>("GrandChild");
childPad.Show();
ITV iTV = container.Resolve<ITV>();
iTV.Show();

2.4 Unity依賴注入,多層架構

////1、聲明一個容器
IUnityContainer container = new UnityContainer();
//2、初始化容器,註冊類型
container.RegisterType<IPhone, ApplePhone>();
container.RegisterType<IMicrophone, Microphone>();
container.RegisterType<IPower, Power>();
container.RegisterType<IHeadphone, Headphone>();

//3、創建對象,通過反射實現
IPhone phone = container.Resolve<IPhone>();
phone.Call();


2.5 Unity生命週期管理

//容器成了創建對象的入口,可以加入自己的管理邏輯:生命週期
//1、聲明一個容器
IUnityContainer container = new UnityContainer();
//2、初始化容器,註冊類型
//container.RegisterType<IPhone, AndroidPhone>();//默認 瞬時

//container.RegisterType<IPhone, AndroidPhone>(new TransientLifetimeManager());//瞬時  每一次都是全新生成

// container.RegisterType<IPhone, AndroidPhone>(new ContainerControlledLifetimeManager());//容器單例  單例就是不要自己實現


//3、創建對象,通過反射實現
//IPhone phone1 = container.Resolve<IPhone>();
//IPhone phone2 = container.Resolve<IPhone>();
//Console.WriteLine(object.ReferenceEquals(phone1, phone2));
//phone1.Call();

#region 線程單例
//線程單例,相同線程的實例相同,不同線程的實例不同,  如web請求/多線程操作
container.RegisterType<IPhone, AndroidPhone>(new PerThreadLifetimeManager());//線程單例  同一個線程就是單例的   不同線程就是不同的
IPhone phone1 = null;
Action action1 = new Action(() =>
{
    phone1 = container.Resolve<IPhone>();
    Console.WriteLine($"iphone1由線程ID={Thread.CurrentThread.ManagedThreadId}");
});
var result1 = action1.BeginInvoke(null, null);

IPhone phone2 = null;
Action action2 = new Action(() =>
{
    phone2 = container.Resolve<IPhone>();
    Console.WriteLine($"iphone2由線程ID={Thread.CurrentThread.ManagedThreadId}");
});


IPhone phone3 = null;
var result2 = action2.BeginInvoke(t =>
{
    phone3 = container.Resolve<IPhone>();
    Console.WriteLine($"iphone3由線程ID={Thread.CurrentThread.ManagedThreadId}");
    Console.WriteLine($"object.ReferenceEquals(phone2, phone3) = {object.ReferenceEquals(phone2, phone3)}");
}, null);

action1.EndInvoke(result1);
action2.EndInvoke(result2);

Console.WriteLine($"object.ReferenceEquals(phone1, phone2) = {object.ReferenceEquals(phone1, phone2)}");
#endregion


//container.RegisterType<IPhone, AndroidPhone>(new HierarchicalLifetimeManager());//分級容器單例
//IUnityContainer unityContainer = container.CreateChildContainer();//獲取子容器

//container.RegisterType<IPhone, AndroidPhone>(new ExternallyControlledLifetimeManager());//外部可釋放單例
//container.RegisterType<IPhone, AndroidPhone>(new PerResolveLifetimeManager());//循環引用  不推薦


3 AOP面向切面編程

<!--<?xml version="1.0" encoding="utf-8" ?>-->
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
  </configSections>
  <unity>
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
    <containers>
      <container name="testContainer">
        <extension type="Interception"/>
        <register type="面向切面編程.UnityWay.IUserProcessor,面向切面編程" mapTo="面向切面編程.UnityWay.UserProcessor, 面向切面編程">
          <interceptor type="InterfaceInterceptor"/>
          <interceptionBehavior type="面向切面編程.UnityWay.ExceptionLoggingBehavior,面向切面編程"/>
          <interceptionBehavior type="面向切面編程.UnityWay.CachingBehavior,面向切面編程"/>
          <interceptionBehavior type="面向切面編程.UnityWay.LogBeforeBehavior,面向切面編程"/>
          <interceptionBehavior type="面向切面編程.UnityWay.ParameterCheckBehavior,面向切面編程"/>
          <interceptionBehavior type="面向切面編程.UnityWay.LogAfterBehavior,面向切面編程"/>
        </register>
      </container>
    </containers>
  </unity>
  
</configuration>
public class ParameterCheckBehavior : IInterceptionBehavior
    {
        public bool WillExecute
        {
            get
            {
                //throw new NotImplementedException();
                return true;
            }
        }

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            //throw new NotImplementedException();
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            //throw new NotImplementedException();
            Console.WriteLine("ParameterCheckBehavior");
            User user = input.Inputs[0] as User;//可以不寫死,反射+特性完成對數據的有效性檢測
            if (user.Pwd.Length<5)
            {
                //返回一個異常
                return input.CreateExceptionMethodReturn(new Exception("密碼長度不能小於10"));
            }
            else
            {
               return getNext().Invoke(input, getNext);
            }
        }
    }
 public class CachingBehavior : IInterceptionBehavior
    {
        private static Dictionary<string, object> CachingDictionary = new Dictionary<string, object>();

        public bool WillExecute
        {
            get
            {
                //throw new NotImplementedException();
                return true;
            }
        }

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            //throw new NotImplementedException();
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            //throw new NotImplementedException();
            Console.WriteLine("CachingBehavior");
            string key = $"{input.MethodBase.Name}_{Newtonsoft.Json.JsonConvert.SerializeObject(input.Inputs)}";
            if (CachingDictionary.ContainsKey(key))
            {
                return input.CreateMethodReturn(CachingDictionary[key]);//相當於短路器  ,直接返回
            }
            else
            {
                IMethodReturn methodReturn = getNext().Invoke(input, getNext);
                if (methodReturn.ReturnValue!=null)
                {
                    CachingDictionary.Add(key, methodReturn.ReturnValue);
                }
                return methodReturn;
            }
        }
    }
 public class ExceptionLoggingBehavior : IInterceptionBehavior
    {
        public bool WillExecute
        {
            get
            {
                //throw new NotImplementedException();
                return true;
            }
        }

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            //throw new NotImplementedException();
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            //throw new NotImplementedException();
            IMethodReturn methodReturn = getNext().Invoke(input, getNext);
            Console.WriteLine("ExceptionLoggingBehavior");
            if (methodReturn.Exception==null)
            {
                Console.WriteLine("無異常");
            }
            else
            {
                Console.WriteLine($"異常:{methodReturn.Exception.Message}");
            }
            return methodReturn;
        }
    }
public class LogAfterBehavior : IInterceptionBehavior
    {
        public bool WillExecute
        {
            get
            {
                return true;
                //throw new NotImplementedException();
            }
        }

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            //throw new NotImplementedException();
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            //throw new NotImplementedException();
            IMethodReturn methodReturn  = getNext().Invoke(input, getNext);
            Console.WriteLine("LogAfterBehavior");
            Console.WriteLine(input.MethodBase.Name);//獲取方法名稱
            foreach (var item in input.Inputs)
            {
                Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(item));
            }
            Console.WriteLine($"返回值:{methodReturn.ReturnValue}");
            return methodReturn;
        }

    }
public class LogBeforeBehavior : IInterceptionBehavior
    {
        public bool WillExecute
        {
            get
            {
                return true;
                //throw new NotImplementedException();
            }
        }

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            // throw new NotImplementedException();
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            // throw new NotImplementedException();
            Console.WriteLine("LogBeforeBehavior");

            //input拿到所有參數信息
            foreach (var item in input.Inputs)
            {
                //反射或者序列化顯示更多信息//install-package Newtonsoft.Json
                Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(item));//install-package Newtonsoft.Json
            }
            //
            return getNext()(input, getNext);//getNext()得到委託實例;
        }
    }
 public class UnityConfigAOP
    {
        public static void Show()
        {
            User user = new User() { Name = "Admin", Pwd = "123" };

            {
                //通過反射創建對象
                IUnityContainer container = new UnityContainer();
                container.RegisterType<IUserProcessor, UserProcessor>();
                IUserProcessor processor = container.Resolve<IUserProcessor>();
                processor.RegUser(user);
            }

            {
                IUnityContainer container = new UnityContainer();
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CfgFiles\\Unity.config");
                Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

                UnityConfigurationSection unityConfigurationSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
                unityConfigurationSection.Configure(container, "testContainer");

                IUserProcessor processor = container.Resolve<IUserProcessor>();
                processor.RegUser(user);
            }

        }
    }

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

    public class UserProcessor : IUserProcessor
    {
        public void RegUser(User user)
        {
            Console.WriteLine($"用戶已註冊,用戶名稱={user.Name} Password={user.Pwd}");
        }
    }

    public class User
    {
        public string Name { get; set; }
        public string Pwd { get; set; }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章