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(
1 2 3 4 5 ); // 计算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.1 2.9 3.1 4 5 );

    
// 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(
1 2 3 4 5 );
    
#endregion

    Console.ReadLine();
}
这回仔细看下,代码中已经完全找不到Addtive,Multiplication等这些具体的类名了,整个程序完全依赖于配置文件中的相关节点(其实OO的角度来讲,是基于接口Icalculate的编程以及不同对象的组合让这一切成为可能)。
如果我们要把乘法运算换成加法运算,太容易了,把DI.config中的
<type type="ICalc" mapTo="Mul"/>   
换成
<type type="ICalc" mapTo="Add"/>
原来的调用代码一行都不用改!
最后:Unity除了实现IOC/DI之外还有一些其它用途,比如:实现单件模式(而且这种实现方式更灵活,比如我们可以让任何一个普通的类,在容器的生命周期内仅返回一个实例,这是传统的单件模式中"把类硬编码定死为单件实例"无法做到的)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值