[IoC容器Unity]第一回:Unity預覽

1.引言

高內聚,低耦合成爲一個OO架構設計的一個參考標準。高內聚是一個模塊或者一個類中成員跟這個模塊或者類的關係儘可能高,低耦合是不一樣模塊或者不一樣類之間關係儘可能簡單。html

拿咱國家舉例來講,假如你是中國人。編程

高內聚:就是說你跟中國親,關係好,國家會保護你。設計模式

低內聚:就是說你跟中國的關係很差,那還怎麼混,改天就要批鬥你,你就是個問題源。緩存

低耦合:就是說你跟日本的關係很是正常,很是簡單,這樣的話,就不會被罵漢奸了。session

高耦合:就是說你跟日本親,活該被砸,被遊街。架構

上面例子虛構的,不太貼切,但從中能夠看出來高內聚和低耦合的處境是最好的。高內聚是對內部成員跟自己這個模塊的關係的描述,低耦合是對成員跟外部模塊之間關係的描述。對內對外也是一個相對範圍,一個模塊裏面的小模塊之間是耦合,對大模塊是聚合,因此說耦合無處不在,咱們都要低耦合,Untity就能夠幫助咱們。app

2.Unity

Unity是一個IoC容器,用來實現依賴注入(Dependency Injection,DI),減小耦合的,Unity出自於偉大的微軟。對依賴注入和IoC模式能夠查看以前一篇文章IoC模式
unity組件網址:http://unity.codeplex.com/
網址中有源碼有文檔有示例,你們能夠下載。我是用的是2.1版本。ide

看看Unity能作些什麼,列舉部分以下:函數

1.Unity支持簡單對象建立,特別是分層對象結構和依賴,以簡化程序代碼。其包含一個編譯那些可能存在依賴於其餘對象的對象實例機制。
2.Unity支持必要的抽象,其容許開發者在運行時或配置去指定依賴關係同時能夠簡單的管理橫切點(AOP)。
3.Unity增長了推遲到容器組件配置的靈活性。其一樣支持一個容器層次的結構。
4.Unity擁有服務定位能力,對於一個程序在許多狀況下重複使用組件來分離和集中功能是很是有用的。
5.Unity容許客戶端儲存或緩存容器。對於在ASP.NET Web applications中開發者將容器持久化於ASP.NET中的session或application中特別有效。
6.Unity擁有攔截能力,其容許開發者經過建立並執行handlers(在方法或屬性被調用到達以前)來爲已存在的組件增長一個函數,並再次爲返回調用結果。
7.Unity能夠從標準配置系統中讀取配置信息,例如:XML文件,同時使用配置文件來配置容器。
8.Unity支持開發者實現自定義容器擴展,例如:你能夠實現方法來容許額外的對象構造和容器特徵,例如緩存。
9.Unity容許架構師和開發者在現代化的程序中更簡單的實現通用設計模式。post

.....

咱們項目中何時要使用到Unity呢,以下狀況:

1.所構建的系統依賴於健全的面向對象原則,可是大量不一樣的代碼交織在一塊兒而難以維護。
2.構建的對象和類須要依賴其餘對象或類。
3.依賴於複雜的或須要抽象的對象。
4.但願利用構造函數、方法或屬性的調用注入優點。
5.但願管理對象實例的生命週期。
6.但願可以在運行時管理並改變依賴關係。
7.但願在攔截方法或屬性調用的時候生成一個策略鏈或管道處理容器來實現橫切(AOP)任務。
8.但願在Web Application中的回發操做時可以緩存或持久化依賴關係。

..............

 

先看看Unity容器IUnityContainer 接口的定義:

View Code
    //Interface defining the behavior of the Unity dependency injection container.
    public interface IUnityContainer : IDisposable
    {
        //The parent of this container.
        IUnityContainer Parent { get; }

        //Get a sequence of Microsoft.Practices.Unity.ContainerRegistration that describe
        //the current state of the container.
        IEnumerable<ContainerRegistration> Registrations { get; }

        //Add an extension object to the container.
        IUnityContainer AddExtension(UnityContainerExtension extension);

        //Run an existing object through the container and perform injection on it.        
        object BuildUp(Type t, object existing, string name, params ResolverOverride[] resolverOverrides);

        //Resolve access to a configuration interface exposed by an extension.
        object Configure(Type configurationInterface);

        //Create a child container. 
        IUnityContainer CreateChildContainer();

        //Register an instance with the container.
        IUnityContainer RegisterInstance(Type t, string name, object instance, LifetimeManager lifetime);

        //Register a type mapping with the container, where the created instances will
        //use the given Microsoft.Practices.Unity.LifetimeManager.
        IUnityContainer RegisterType(Type from, Type to, string name, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers);
 
        //Remove all installed extensions from this container.
        IUnityContainer RemoveAllExtensions();

        //Resolve an instance of the requested type with the given name from the container.
        object Resolve(Type t, string name, params ResolverOverride[] resolverOverrides);

        //Return instances of all registered types requested.
        IEnumerable<object> ResolveAll(Type t, params ResolverOverride[] resolverOverrides);

        //Run an existing object through the container, and clean it up.
        void Teardown(object o);
    }

IUnityContainer 中有幾個方法常常會使用到,如:RegisterInstance,RegisterType,Resolve等等。

Unity爲了方便操做,專門爲IUnityContainer 提供了許多的擴展方法,部分方法聲明如:

View Code
    /// <summary>
    /// 擴展方法 v2.0.50727
    /// </summary>
    public static class UnityContainerExtensions
    {
        public static IUnityContainer AddNewExtension<TExtension>(this IUnityContainer container) where TExtension : UnityContainerExtension;
        public static T BuildUp<T>(this IUnityContainer container, T existing, params ResolverOverride[] resolverOverrides);
        public static T BuildUp<T>(this IUnityContainer container, T existing, string name, params ResolverOverride[] resolverOverrides);
        public static object BuildUp(this IUnityContainer container, Type t, object existing, params ResolverOverride[] resolverOverrides);
        public static TConfigurator Configure<TConfigurator>(this IUnityContainer container) where TConfigurator : IUnityContainerExtensionConfigurator;
        public static bool IsRegistered<T>(this IUnityContainer container);
        public static bool IsRegistered<T>(this IUnityContainer container, string nameToCheck);
        public static bool IsRegistered(this IUnityContainer container, Type typeToCheck);
        public static bool IsRegistered(this IUnityContainer container, Type typeToCheck, string nameToCheck);
        public static IUnityContainer RegisterInstance<TInterface>(this IUnityContainer container, TInterface instance);
        public static IUnityContainer RegisterInstance<TInterface>(this IUnityContainer container, string name, TInterface instance);
        public static IUnityContainer RegisterInstance<TInterface>(this IUnityContainer container, TInterface instance, LifetimeManager lifetimeManager);
        public static IUnityContainer RegisterInstance(this IUnityContainer container, Type t, object instance);
        public static IUnityContainer RegisterInstance<TInterface>(this IUnityContainer container, string name, TInterface instance, LifetimeManager lifetimeManager);
        public static IUnityContainer RegisterInstance(this IUnityContainer container, Type t, object instance, LifetimeManager lifetimeManager);
        public static IUnityContainer RegisterInstance(this IUnityContainer container, Type t, string name, object instance);
        public static IUnityContainer RegisterType<T>(this IUnityContainer container, params InjectionMember[] injectionMembers);
        public static IUnityContainer RegisterType<TFrom, TTo>(this IUnityContainer container, params InjectionMember[] injectionMembers) where TTo : TFrom;
        public static IUnityContainer RegisterType<T>(this IUnityContainer container, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers);
        public static IUnityContainer RegisterType<TFrom, TTo>(this IUnityContainer container, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers) where TTo : TFrom;
        public static IUnityContainer RegisterType<TFrom, TTo>(this IUnityContainer container, string name, params InjectionMember[] injectionMembers) where TTo : TFrom;
        public static IUnityContainer RegisterType<T>(this IUnityContainer container, string name, params InjectionMember[] injectionMembers);
        public static IUnityContainer RegisterType(this IUnityContainer container, Type t, params InjectionMember[] injectionMembers);
        public static IUnityContainer RegisterType<T>(this IUnityContainer container, string name, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers);
        public static IUnityContainer RegisterType<TFrom, TTo>(this IUnityContainer container, string name, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers) where TTo : TFrom;
        public static IUnityContainer RegisterType(this IUnityContainer container, Type t, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers);
        public static IUnityContainer RegisterType(this IUnityContainer container, Type t, string name, params InjectionMember[] injectionMembers);
        public static IUnityContainer RegisterType(this IUnityContainer container, Type from, Type to, params InjectionMember[] injectionMembers);
        public static IUnityContainer RegisterType(this IUnityContainer container, Type t, string name, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers);
        public static IUnityContainer RegisterType(this IUnityContainer container, Type from, Type to, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers);
        public static IUnityContainer RegisterType(this IUnityContainer container, Type from, Type to, string name, params InjectionMember[] injectionMembers);
        public static T Resolve<T>(this IUnityContainer container, params ResolverOverride[] overrides);
        public static T Resolve<T>(this IUnityContainer container, string name, params ResolverOverride[] overrides);
        public static object Resolve(this IUnityContainer container, Type t, params ResolverOverride[] overrides);
        public static IEnumerable<T> ResolveAll<T>(this IUnityContainer container, params ResolverOverride[] resolverOverrides);

        public static IUnityContainer LoadConfiguration(this IUnityContainer container);
        public static IUnityContainer LoadConfiguration(this IUnityContainer container, string containerName);
        public static IUnityContainer LoadConfiguration(this IUnityContainer container, UnityConfigurationSection section);
        public static IUnityContainer LoadConfiguration(this IUnityContainer container, UnityConfigurationSection section, string containerName);
    }

 

下面來個簡單的例子,如今項目中添加Microsoft.Practices.Unity.dll和Microsoft.Practices.Unity.Configuration.dll的引用,準備幾個類,以下:

View Code
    /// <summary>
    /// 班級接口
    /// </summary>
    public interface IClass
    {
        string ClassName { get; set; }

        void ShowInfo();
    }
    /// <summary>
    /// 計科班
    /// </summary>
    public class CbClass : IClass
    {
        public string ClassName { get; set; }

        public void ShowInfo()
        {
            Console.WriteLine("計科班:{0}", ClassName);
        }
    }
    /// <summary>
    /// 電商班
    /// </summary>
    public class EcClass : IClass
    {
        public string ClassName { get; set; }

        public void ShowInfo()
        {
            Console.WriteLine("電商班:{0}", ClassName);
        }
    }

 

用編程方式實現注入:

View Code
        public static void ContainerCodeTest1()
        {
            IUnityContainer container = new UnityContainer();
            
            //默認註冊(無命名),若是後面還有默認註冊會覆蓋前面的
            container.RegisterType<IClass, CbClass>();
          
            //命名註冊
            container.RegisterType<IClass, EcClass>("ec");

            //解析默認對象
            IClass cbClass = container.Resolve<IClass>();
            cbClass.ShowInfo();

            //指定命名解析對象
            IClass ecClass = container.Resolve<IClass>("ec");           
            ecClass.ShowInfo();

            //獲取容器中全部IClass的註冊的已命名對象
            IEnumerable<IClass> classList = container.ResolveAll<IClass>();
            foreach (var item in classList)
            {
                item.ShowInfo();
            }
        }

 

配置文件方式:

View Code
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <!--定義類型別名-->
    <aliases>
      <add alias="IClass" type="ConsoleApplication1.UnityDemo.IClass,ConsoleApplication1" />
      <add alias="CbClass" type="ConsoleApplication1.UnityDemo.CbClass,ConsoleApplication1" />
      <add alias="EcClass" type="ConsoleApplication1.UnityDemo.EcClass,ConsoleApplication1" />
    </aliases>
    <!--容器-->
    <container name="FirstClass">
      <!--映射關係-->
      <register type="IClass"  mapTo="CbClass"></register>
      <register type="IClass" name="ec" mapTo="EcClass"></register>
    </container>
  </unity>
</configuration>
View Code
        public static void ContainerConfigurationTest1()
        {
            IUnityContainer container = new UnityContainer();
            string configFile = "http://www.cnblogs.com/UnityDemo/Constructor/Unity.config";
            var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = configFile };
            //從config文件中讀取配置信息
            Configuration configuration =
                ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            //獲取指定名稱的配置節
            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

            //載入名稱爲FirstClass 的container節點
            container.LoadConfiguration(section, "FirstClass");

           //解析默認對象
            IClass cbClass = container.Resolve<IClass>();
            cbClass.ShowInfo();

            //指定命名解析對象
            IClass ecClass = container.Resolve<IClass>("ec");           
            ecClass.ShowInfo();

            //獲取容器中全部IClass的註冊的已命名對象
            IEnumerable<IClass> classList = container.ResolveAll<IClass>();
            foreach (var item in classList)
            {
                item.ShowInfo();
            }
        }

效果跟代碼方式同樣

Unity使用方式基本分爲三步:

  1. 聲明容器IUnityContainer
  2. Register註冊類型
  3. Resolve解析類型對象

3.小結

看到IUnityContainer接口聲明仍是比較簡單的,主要用到的方法也很少,另外提供了擴展方法,看起來代碼挺多,都是一些方法重載,不要對Unity組建感到恐懼,咱們只是簡單的使用它,主要是使用IUnityContainer。

相關文章
相關標籤/搜索