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
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    jQuery-选择器
    Html-CSS-细节处理
    JS-练习题
    将博客搬至CSDN
    Linux学习(推荐学习资源)——保持更新
    借助Git实现本地与GitHub远程双向传输(同步GitHub仓库)以及一些使用错误解决
    Linux学习使用Vim
    linux学习之Ubuntu
    在docker中创建使用MySQL,并实现远程连接navicat
    Swing系列之控件一
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1494449.html
Copyright © 2011-2022 走看看