惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Security Latest
Security Latest
C
CXSECURITY Database RSS Feed - CXSecurity.com
AI
AI
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
P
Palo Alto Networks Blog
Spread Privacy
Spread Privacy
Project Zero
Project Zero
Google Online Security Blog
Google Online Security Blog
The Cloudflare Blog
L
LangChain Blog
T
Tenable Blog
GbyAI
GbyAI
C
Cybersecurity and Infrastructure Security Agency CISA
大猫的无限游戏
大猫的无限游戏
Last Week in AI
Last Week in AI
量子位
Cloudbric
Cloudbric
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
美团技术团队
S
Secure Thoughts
P
Privacy & Cybersecurity Law Blog
S
Securelist
S
Schneier on Security
F
Full Disclosure
Engineering at Meta
Engineering at Meta
A
Arctic Wolf
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
爱范儿
爱范儿
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
P
Privacy International News Feed
宝玉的分享
宝玉的分享
A
About on SuperTechFans
博客园 - 【当耐特】
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hugging Face - Blog
Hugging Face - Blog
Webroot Blog
Webroot Blog
Google DeepMind News
Google DeepMind News
H
Heimdal Security Blog
Y
Y Combinator Blog
月光博客
月光博客
H
Hacker News: Front Page
MongoDB | Blog
MongoDB | Blog
C
Check Point Blog
TaoSecurity Blog
TaoSecurity Blog
腾讯CDC
N
Netflix TechBlog - Medium

博客园 - 眼里进了砂

Unity Application Block 與 ASP.NET MVC 學習資源整理 [转] 线程之间的通讯---SynchronizationContext [转] .NET2.0中WinForm自定义的程序配置[转] 使用BackgroundWorker组件进行异步操作编程[转] .NET页面事件执行顺序[转] 不用设置iis .net 实现urlrewrite[转] 利用XPath读取Xml文件 javascript中replace与正则表达式 c# BackgroundWorker组件介绍(属性、方法、事件) .net 2.0 BackgroundWorker类详细用法 .Net的线程同步方法一:ManualResetEvent .NET应用程序中异步调用Web Service的几种方法 come from: veryhappy(wx.net) [转][javascript] Google谷歌首页点点效果 AJAX 中Sys.WebForms.PageRequestManager的事件激发顺序 AJAX 中Sys.Net.WebRequestManager的事件激发顺序 Summary review about Problem.Design.Solution 2 Summary review about Problem.Design.Solution [转发]深入理解 __doPostBack CSS Tips
Unity Application Block 1.2 学习笔记 [转]
眼里进了砂 · 2009-12-23 · via 博客园 - 眼里进了砂

昨天花了一天时间,把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之外还有一些其它用途,比如:实现单件模式(而且这种实现方式更灵活,比如我们可以让任何一个普通的类,在容器的生命周期内仅返回一个实例,这是传统的单件模式中"把类硬编码定死为单件实例"无法做到的)