之前Terry Lee 已经介绍过Unity的简单使用了,不过那篇文章是针对旧版本的,现在的版本1.2版略有不同。
我下载了Unity并做了一个简单的测试,项目的分布是这个样子:
LoggerTest.Interface.ILogger 主要是接口, 一个简单的不能再简单的方法结构:
public interface ILogger
{
void Write(string message);
}
LoggerTest 是实现这个接口的project, 恩,跟Terry Lee 的例子一样,实现两个就OK了,分别是FlatFileLogger和DatabaseLogger。
namespace LoggerTest
{
public class FlatFileLogger : ILogger
{
public void Write(string message)
{
Console.WriteLine(String.Format("Message:{0}", message));
Console.WriteLine("Target:FlatFile");
}
}
public class DatabaseLogger : ILogger
{
public void Write(string message)
{
Console.WriteLine(String.Format("Message:{0}", message));
Console.WriteLine("Target:Database");
}
}
}
下面是Unity出场的时候了,可能初学者不知道要引用哪些组件(像我就是),这里截个图告诉大家:
如果是显示注入,调用Microsoft.Practices.Unity 和Microsoft.Practices.ObjectBuilder2 就可以了;如果是通过配置文件注入,那么就要另外引用Microsoft.Practices.Unity.Configuration
好了,那么基本上就大功告成,代码里已经注释的很清楚了
//显式获取UnityContainer
private IUnityContainer GetContainer_Directly()
{
IUnityContainer container = new UnityContainer();
//如果注册多个类型需要指定名字(名字是任意的)
//否则当调用ResolveAll<>()时,那些没有指定名字的将会获取不到
//但是,Resolve<>() 会默认取那些空名字的注入对象。
container.RegisterType<ILogger, DatabaseLogger>("databaseLogger");
container.RegisterType<ILogger, FlatFileLogger>("flatfileLogger");
return container;
}
//从配置文件获取UnityContainer
private IUnityContainer GetContainer_Config()
{
IUnityContainer container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)System.Configuration.ConfigurationManager.GetSection("unity");
section.Containers[0].Configure(container);
return container;
}
public void Test()
{
IUnityContainer container = GetContainer_Config();
foreach (ILogger logger in container.ResolveAll<ILogger>())
logger.Write("Bruce Lee");
}
配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<containers>
<container name="One">
<types>
<type type="LoggerTest.Interface.ILogger, LoggerTest.Interface" name="FlatFileLogger"
mapTo="LoggerTest.FlatFileLogger, LoggerTest"/>
<type type="LoggerTest.Interface.ILogger, LoggerTest.Interface" name="DatabaseLogger"
mapTo="LoggerTest.DatabaseLogger, LoggerTest"/>
</types>
</container>
</containers>
</unity>
</configuration>
运行效果:
后记:Unity的简单介绍
以下摘自贪睡虫: http://www.cnblogs.com/liujian969/archive/2009/01/17/1377446.html
描述
Unity 应用程序块(Unity)是一个轻量级、可扩展的依赖注入容器,支持构造函数、属性和方法调用注入。它为开发人员提供了如下好处:
- 简化了对象的创建,尤其是分层的对象结构和依赖。
- 允许开发人员在运行时或者配置中指定依赖的需求抽象,以及简化了横切关注点的管理。
- 服务定位功能允许客户代码保存或者缓存容器。这在开发人员可以持久化容器到 ASP.NET Session 或者 Application 中的 ASP.NET Web 应用程序中特别有用。
常见场景
除了单独解决横切关注点如日志、认证、授权、缓存和异常处理的组件以外,现代业务系统通常由定制的业务对象和在应用程序中完成特殊的或者一般的任务的组件组成。
成功构建这样的应用程序的关键是获得解耦的或者极度松耦合的设计。松耦合的应用程序更加灵活、更加易于维护。同时在开发期间进行测试,可以模拟对象的桩(轻量级模拟的实现),这增强了实质的依赖。例如,数据库连接、网络连接、ERP 连接和富用户接口组件。
依赖注入是一种用于构建松耦合应用程序的主要技术。它提供了处理对象间依赖的方法。例如,一个处理用户信息的对象可能依赖于访问数据存储、验证信息和检查用户是否被授权执行更新的其他对象。依赖注入技术可以确保用户类正确的初始化及组装所有这些对象,特别是依赖是抽象的地方。
使用容器可以有很多好处,但它会改变应用程序的设计方式,尤其适合于基于组件的开发,朋友们可以有选择的使用它。