zoukankan      html  css  js  c++  java
  • Unity Application Block 1.2 学习笔记

    昨天花了一天时间,把IOC/DI的相关文章以及Unity相关的一些文章基本在园子里搜了个遍

    先给出几篇不错的文章链接:

    Unity Application Block官方网址 http://www.codeplex.com/unity

    吕震宇整理的[Object Builder Application Block] http://www.cnblogs.com/zhenyulu/articles/641728.html

    吕震宇[你真的了解Ioc与AOP吗?] http://www.cnblogs.com/zhenyulu/articles/233966.html

    坚强2002翻译的[Inversion of Control Containers and the Dependency Injection pattern] http://www.cnblogs.com/me-sa/archive/2008/07/30/IocDI.html

    赤脚小子的[unity系列] http://www.cnblogs.com/kebixisimba/archive/2008/05/19/1202467.html
     
    NEE's [Unity 配置:typeConverter的使用] http://www.cnblogs.com/nickyao/archive/2008/05/04/1181804.html

    Warmth & Chilliness的[Unity -- .NET下的原生Ioc框架,让一部分人先用起来] http://www.cnblogs.com/think8848/archive/2008/10/25/1319616.html

    基本上把上面的这些个文章全耐着性子看完,相关知识点的“扫盲”工作也差不多完成了

    这里只是把我练习的一个例子贴在这里,并发表一些个人粗浅的看法

    应用场景:随便给一些数字,要求对这些数字进行一项基本的数据运算(例子中只实现了加法/乘法)

    先添加对Microsoft.Practices.Unity.dll的引用

    准备测试用的接口和类:

    /// <summary>
        
    /// 接口
        
    /// </summary>
        public interface Icalculate
        {
            
    int Calculate(params int[] a);

            
    double Calculate(params double[] a);

            
    string GetOperationName();

            
        }

        
    /// <summary>
        
    /// 加法运算
        
    /// </summary>
        public class Addtive : Icalculate
        {
            
    /// <summary>
            
    /// 注意:至少要有一个构造函数,否则用配置文件方式Resolve<Icalculate>时会提示:Icalculate是一个接口,没有构造函数,所以不能创建实例云云,但有趣的是用硬编码方式却可以成功
            
    /// </summary>
            public Addtive() { }

            
    public int Calculate(params int[] a)
            {
                
    int Result = 0;

                
    foreach (int x in a)
                {
                    Result 
    += x;
                }

                
    return Result;
            }

            
    public double Calculate(params double[] a)
            {
                
    double Result = 0.0;

                
    foreach (double x in a)
                {
                    Result 
    += x;
                }

                
    return Result;
            }

            
    public string GetOperationName()
            {
                
    return "加法";
            }
        }

        
    /// <summary>
        
    /// 乘法运算
        
    /// </summary>
        public class Multiplication : Icalculate
        {

            
    public Multiplication() { }

            
    public int Calculate(params int[] a)
            {
                
    int Result = 1;

                
    foreach (int x in a)
                {
                    Result 
    *= x;
                }

                
    return Result;
            }

            
    public double Calculate(params double[] a)
            {
                
    double Result = 1.0;

                
    foreach (double x in a)
                {
                    Result 
    *= x;
                }

                
    return Result;
            }

            
    public string GetOperationName()
            {
                
    return "乘法";
            }
        }

        
    /// <summary>
        
    /// (四则)运算管理器
        
    /// </summary>
        public class CalcManager
        {
            
    private Icalculate _calc;


            
    public CalcManager(Icalculate IC)
            {
                _calc 
    = IC;
            }

            
    //[InjectionMethod]
            
    //public void SetCalculate(Icalculate IC) {
            
    //    _calc = IC;
            
    //}

            
    public void Compute(params int[] a)
            {
                
    string _paramName = "";

                
    foreach (int x in a)
                {
                    _paramName 
    += x.ToString() + ",";
                }
                _paramName 
    = _paramName.Trim(',');

                Console.WriteLine(
    "{0} {1}计算结果:{2}", _paramName, _calc.GetOperationName(), _calc.Calculate(a));
            }

            
    public void Compute(params double[] a)
            {
                
    string _paramName = "";

                
    foreach (double x in a)
                {
                    _paramName 
    += x.ToString() + ",";
                }
                _paramName 
    = _paramName.Trim(',');

                Console.WriteLine(
    "{0} {1}计算结果:{2}", _paramName, _calc.GetOperationName(), _calc.Calculate(a));
            }

        }
    为了对比,我们先用传统方式来调用试下:
    static void Main(string[] args)
    {
        
    #region 不用依赖注入的传统方式
        CalcManager CM 
    = new CalcManager(new Addtive());
        CM.Compute(
    12345);//计算1,2,3,4,5的和

        
    //CM = new CalcManager(new Multiplication());
        
    //CM.Compute(1, 2, 3, 4, 5);//计算1,2,3,4,5的乘积
        #endregion            

        Console.ReadLine();
    }
    虽然简单易懂,但细想一下可扩展性并不高,如果以后又增加了除法,平方,减法...等一系列算法,不是每次都要这一段代码吗?原因就是接口,算法实体类,调用程序之间的耦合性太高
    接下来,我们用Unity换一种写法:
    using System;
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.Configuration;
    using System.Configuration;

    static void Main(string[] args)
    {
        

        
    #region 使用依赖注入(硬编码方式)
        IUnityContainer container 
    = new UnityContainer();
        container.RegisterType
    <Icalculate, Addtive>() //注入加法类
             .RegisterType<CalcManager>();//注入管理器            


        CalcManager CM 
    = container.Resolve<CalcManager>();//取得CalcManager的实例
        CM.Compute(1.12.93.145);

        
    //container.RegisterType<Icalculate, Multiplication>();//继续注入乘法类

        
    //CM = container.Resolve<CalcManager>();
        
    //CM.Compute(1, 2, 3, 4, 5);
        #endregion

        

        Console.ReadLine();
    }
    单从代码上看,只不过换了种写法和思路,但仍然属于“硬编码”的方式,如果要增加其它算法或换成其它算法,一样还是要改这段代码.(貌似纯属瞎折腾?呵呵)
    下面切入正题,Unity除了这种硬编码方式,还允许把注入规则/映射写到配置文件里
    先修改App.Config,内容大致如下:
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      
    <configSections>
        
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=1.2.0.0, Culture=neutral" />
      
    </configSections>
      
    <unity configSource="config\DI.config" />
    </configuration>
    同时再新建一个config目录,把DI.config文件放在该目录下,内容:
    <?xml version="1.0" ?>
    <unity>
      
    <typeAliases>
        
    <typeAlias alias="ICalc" type="UnityStudy.Icalculate, UnityStudy" />
        
    <typeAlias alias="Add" type="UnityStudy.Addtive, UnityStudy" />
        
    <typeAlias alias="Mul" type="UnityStudy.Multiplication, UnityStudy" />
        
    <typeAlias alias="CM" type="UnityStudy.CalcManager, UnityStudy" />
      
    </typeAliases>
      
    <containers>
        
    <container>
          
    <types>
            
    <type type="ICalc" mapTo="Mul"/>      
            
    <!--结实验,下面这一行加不加程序都能运行,只要确保CalcManager中有一个参数为Icalculate的构架函数或(注入)设置方法就行[参看CalcManager中注释掉的部分],Unity在这一点上确实比较“智能”-->
            
    <type type="CM"/>       
          
    </types>
        
    </container>
      
    </containers>
    </unity>

    调用代码再换一种写法:
    static void Main(string[] args)
    {
        
        
    #region 使用依赖注入(配置文件方式)
        IUnityContainer container 
    = new UnityContainer();
        UnityConfigurationSection section 
    = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
        section.Containers.Default.Configure(container);

        CalcManager CM 
    = container.Resolve<CalcManager>();
        CM.Compute(
    12345);
        
    #endregion

        Console.ReadLine();
    }
    这回仔细看下,代码中已经完全找不到Addtive,Multiplication等这些具体的类名了,整个程序完全依赖于配置文件中的相关节点(其实OO的角度来讲,是基于接口Icalculate的编程以及不同对象的组合让这一切成为可能)。
    如果我们要把乘法运算换成加法运算,太容易了,把DI.config中的
    <type type="ICalc" mapTo="Mul"/>   
    换成
    <type type="ICalc" mapTo="Add"/>
    原来的调用代码一行都不用改!
    最后:Unity除了实现IOC/DI之外还有一些其它用途,比如:实现单件模式(而且这种实现方式更灵活,比如我们可以让任何一个普通的类,在容器的生命周期内仅返回一个实例,这是传统的单件模式中"把类硬编码定死为单件实例"无法做到的)
    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    day01--计算机硬件基础笔记
    22 Jun 18 Django,ORM
    21 Jun 18 Django,ORM
    20 Jun 18 复习, mysql
    20 Jun 18 Django,ORM
    19 Jun 18 复习, 正则表达式
    19 Jun 18 Django
    15 Jun 18 复习, shutil模块
    15 Jun 18 Django
    14 Jun 18 复习, form表单
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1494449.html
Copyright © 2011-2022 走看看