Microsoft Unity使用-實例注入


Unity是一個輕量級AOP框架,提供構造注入、攔截注入、屬性注入、方法注入,使用起來很方便

一、簡單實例注入

先看一個應用場景。一個應用程序中我想定義一個窗口,做為用戶UI,窗口有高度和寬度兩種屬性

namespace ConsoleUnityDemo
{
    public class MyWindow
    {
        public int Height { get; set; }
        public int Width { get; set; }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            MyWindow myWindow = new MyWindow();
            myWindow.Height = 80;
            myWindow.Width = 100;           
           Console.WriteLine(string.Format("Width:{0}  Height:{1}", myWindow.Width, myWindow.Height));
        }
    }
}

窗口的高屬性會經常改變,所以要將myWindow實例的屬性移到配置中,通常會在<appsetting/>中通過<add key />來添加配置,這樣的話需要加兩個配置,如

<appSettings>
  <add key="Height" value="200"/>
  <add key="Width" value="300"/>
</appSettings>

但是如果應用程序中有兩個MyWindow實例呢?再加上<add key=”Heithgt2”/><add key=”Width2”/>嗎?那再多呢?

Unity提供了輕松實例注入的功能,將對象的實例化移到了應用程序的外部。使用Unity要先引用以下類庫,Unit下載:http://http://unity.codeplex.com/

Microsoft.Practices.Unity.dll 
Microsoft.Practices.Unity.Configuration.dll

修改為以下代碼

namespace ConsoleUnityDemo
{
    public class MyWindow
    {
        public int Height { get; set; }
        public int Width { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            UnityConfigurationSection unitySection = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            UnityContainer unityContainer = new UnityContainer(); 
            unitySection.Configure(unityContainer); //獲取容器
            MyWindow myWindow = unityContainer.Resolve<MyWindow>("FirstMyWindow");  //取實例

            Console.WriteLine(string.Format("Width:{0}  Height:{1}", myWindow.Width, myWindow.Height));
        }
    }
}

App.config配置

<?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">
    <alias alias="MyWindow" type="ConsoleUnityDemo.MyWindow, ConsoleUnityDemo" />
    <container>
      <register type="MyWindow" name="FirstMyWindow" mapTo ="MyWindow">
        <property name="Height" value="80" type="int" />
        <property name="Width" value="100" type="int" />
      </register>
    </container>
  </unity>
  <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
<appSettings>
</appSettings>
</configuration>

 

configSections中section添加了一個名為Unity容器,<unity/>節點的注冊了MyWindow類,別名為MyWindow,type中填寫類型的完整名稱和類型的命名空間,<container/>節點下<register/>注冊一個新實例,這樣一來MyWindow實例屬性就被移除到程序外部了。實際應用中,通常有多種類型的MyWindow,應該將MyWindow象為接口。

image

配置文件做如下修改

<?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">
    <alias alias="MyWindow" type="ConsoleUnityDemo.MyWindow, ConsoleUnityDemo" />
    <alias alias="IWindow" type="ConsoleUnityDemo.IWindow, ConsoleUnityDemo" />
    <container>
      <register type="IWindow" name="FirstMyWindow" mapTo ="MyWindow">
        <property name="Height" value="80" type="int" />
        <property name="Width" value="100" type="int" />
      </register>
    </container>
  </unity>
  <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
<appSettings>
</appSettings>
</configuration>

添加alias別名為IWindow的IWindow類型。register注冊為IWindow, mapTo為實際要創建的類,這就如同

 IWindow MyFirstWindow = new MyWindow

再看看工場模式,創建window改用模塊方法:

image

工場模式中需要IWindow泛化,還需要一個在場類,這樣才能和Window解偶,並且需要修改Factory方法才可以創建新的Window。使用Unit容器中<register/>的mapTo屬性就可以輕松實現工場模式了,Unity替代了Factory的工作。再看下抽象工場:

image

現在需要在一種window中創建一個配套的menu,所以使用了抽象工場,在Client中獲取實現IAbstracgtFactory的工場就可以創建一套window. 抽象工場中會定義多個,如MyWindowFactory,OtherWindowFactory。在Unity中通過修改Cantoner name屬性就可輕松搞寫

namespace ConsoleUnityDemo
{
    public interface IWindow
    {
        int Height { get; set; }
        int Width { get; set; }

        void Show();
    }

    public interface IMenu
    {
        string MenuText { get; set; }
        string MenuColor { get; set; }
    }

    public class MyWindow : IWindow
    {
        public int Height { get; set; }
        public int Width { get; set; }

        public void Show()
        {
            Console.WriteLine("Show MyWindow");
        }
    }

    public class MyMenu : IMenu
    {

        public string MenuText
        {
            get;
            set;

        }

        public string MenuColor
        {
            get;
            set;
        }
    }
    

    class Program
    {
        static void Main(string[] args)
        {
            UnityConfigurationSection unitySection = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            UnityContainer unityContainer = new UnityContainer();
            unitySection.Configure(unityContainer, "AbstractFactory"); //獲取容器
            IWindow myWindow = unityContainer.Resolve<IWindow>("FirstMyWindow");  //取實例
            IMenu myMenu = unityContainer.Resolve<IMenu>("FirstMyMenu");

            Console.WriteLine(string.Format("Width:{0}  Height:{1}", myWindow.Width, myWindow.Height));

        }
    }
}

配置文件如下,將container name屬性設置為AbstractFacotry,代碼中用unitySection.Configure(unityContainer, "AbstractFactory"); 獲取工場。如果增加一個工場,則添加一個Container

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="MyWindow" type="ConsoleUnityDemo.MyWindow, ConsoleUnityDemo" />
    <alias alias="IWindow" type="ConsoleUnityDemo.IWindow, ConsoleUnityDemo" />
    <alias alias="IMenu" type="ConsoleUnityDemo.IMenu, ConsoleUnityDemo" />
    <alias alias="MyMenu" type="ConsoleUnityDemo.MyMenu, ConsoleUnityDemo" />
    <container name="AbstractFactory">
      <register type="IWindow" name="FirstMyWindow" mapTo ="MyWindow">
        <property name="Height" value="80" type="int" />
        <property name="Width" value="100" type="int" />
      </register>
      <register type="IMenu" name="FirstMyMenu" mapTo ="MyMenu">
        <property name="MenuText" value="testValue" />
        <property name="MenuColor" value="ColorValue" />
      </register>
    </container>
  </unity>


免責聲明!

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



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