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>
posted @ 2013-01-27 03:37  徐某人  阅读(6437)  评论(0编辑  收藏  举报