加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 程序设计 > 正文

使用Unity 实现依赖注入

发布时间:2020-05-22 15:57:47 所属栏目:程序设计 来源:互联网
导读:家人身体不太好,好几天没在园子里发帖了。 新项目还是要用MVC3,team 计划使用 Unity。看了一下网上的资料,都是比较老的了,官网也没什么好的指引。MVC也在更新,Unity也在更新。花了1天半时间去MSDN,PP查资料,整理了一下分享给大家。言归正传: 什么是Un

家人身体不太好,好几天没在园子里发帖了。

新项目还是要用MVC3,team 计划使用 Unity。看了一下网上的资料,都是比较老的了,官网也没什么好的指引。MVC也在更新,Unity也在更新。花了1天半时间去MSDN,P&P查资料,整理了一下分享给大家。言归正传:


什么是Unity?

Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入。Unity可以处理那些从事基于组件的软件工程的开发人员所面对的问题。构建一个成功应用程序的关键是实现非常松散的耦合设计。松散耦合的应用程序更灵活,更易于维护。这样的程序也更容易在开发期间进行测试。你可以模拟对象,具有较强的具体依赖关系的垫片(轻量级模拟实现),如数据库连接,网络连接,ERP连接,和丰富的用户界面组件。例如,处理客户信息的对象可能依赖于其他对象访问的数据存储,验证信息,并检查该用户是否被授权执行更新。依赖注入技术,可确保客户类正确实例化和填充所有这些对象,尤其是在依赖可能是抽象的 。

如何得到Unity?

您可以访问http://unity.codeplex.com/releases得到最新版本的Unity现在。当然,如果您在您的visual studio 中安装了Nuget 包管理器,你可以直接在Nuget中获取到最新版本的Unity。

API

UnityContainer.RegisterType<ITFrom,TTO>();

UnityContainer.RegisterType< ITFrom,TTO >();

UnityContainer.RegisterType< ITFrom,TTO >("keyName");

IEnumerable<T> databases = UnityContainer.ResolveAll<T>();

IT instance = UnityContainer.Resolve<IT>();

T instance = UnityContainer.Resolve<T>("keyName");

UnitContainer.RegisterInstance<T>("keyName",new T());

UnityContainer.BuildUp(existingInstance);

IUnityContainer childContainer1 = parentContainer.CreateChildContainer();

代码举例

在开始之前我们要先做一些准备工作。首先创建一个控制台应用程序。使用Nuget 添加Unity到当前项目中。我们可以发现,dll引用中多了3个dll:Microsoft.Practices.ServiceLocation,Microsoft.Practices.Unity和Microsoft.Practices.Configuation。

示例1:根据接口依赖创建类

上边简单介绍了Unity的API。如果在没有注册的情况下Resolve一个类型会发生什么呢?

假设我们需要对日志进行处理。我们先声明一个接口ILogger:

  public interface ILogger
    {
        void Write(string log);

    }

我们可以有多种方法实现这个接口,我们假设希望写日志到文件中:

  public class FileLogger:ILogger
    {

        #region ILogger Members

        public void Write(string log)
        {
            Console.WriteLine("Write log in file.");
        }

        #endregion
    }

我们在实际生活中对数据库的选择也是多种多样的。我们创建一个数据库的基类:

public class Database
    {
    }

创建一个派生类:

public class CustomerDatabase : Database
    {
        private ILogger _logger;
        public CustomerDatabase(ILogger logger)
        {
            _logger = logger;
        }
    }

注意它的构造器的参数是ILogger类型。首先我们要创建一个Unity 容器:

UnityContainer container = new UnityContainer();

接下来我们需要在容器中注册一种类型,它是一个类型的映射,接口类型是ILogger,我希望返回的类型是FileLogger:

container.RegisterType<ILogger,FileLogger>();

然后我们使用Resolve 方法:

Database database = container.Resolve<CustomerDatabase>();

经过调试我们可以发现,如果在容器中没有注册的类型。执行Resolv方法后,Unity尝试创建该类型,会执行该类的构造器。最后database变量的类型就是CustomerDatabase,而且它的私有字段ILogger的当前实例也为FileLogger。

示例2:类型映射

我们希望返回一个日志类的实例,无论它是哪个实现类。我们可以直接在Resolve的类型中指定类型为接口ILogger:

UnityContainer container = new UnityContainer();
container.RegisterType<ILogger,FileLogger>();
ILogger logger = container.Resolve<ILogger>();

每一次 container都会给我们返回一个新的logger实例。

示例3:单例模式的注册

如果我们想告诉Unity,我们想控制生命周期,我们想用单例模式。RegisterType方法包含一个重载,将使用LifetimeManager。每次我们在想获得到database实例时,unity总是会返回第一次我创建的CustomerDatabase。

UnityContainer container = new UnityContainer();
container.RegisterType<Database,CustomerDatabase>
       (new ContainerControlledLifetimeManager());

示例4:注册时附带key

在我们向容器里注册时,可以附带一个string 类型的Key值。

UnityContainer container = new UnityContainer();
         container.RegisterType<Database,SQLDatabase>("SQL");
         container.RegisterType<Database,ORACLEDatabase>("ORACLE");
         IEnumerable<Database> databases = container.ResolveAll<Database>();
         Database database = container.Resolve<Database>("SQL");

我们分别向容器中注册了名为“SQL“和”ORACLE“的Database。当我们使用ResolverAll方法是。容器会返回容器中所有类型为Database的类。

这时我们如果仅仅想回去SQL的实例,我们可以使用container.Resolve<Database>("SQL");

示例5:注册已经存在的实例

通过下边方式我们可以在container中注册一个实例:

  UnityContainer container = new UnityContainer();
  container.RegisterInstance<Database>(new SQLDatabase());
  container.RegisterInstance<Database>("Oracle",new ORACLEDatabase());
  Database database = container.Resolve<Database>();
  Database oracleDatabase = container.Resolve<Database>("Oracle");

看起来和上边的方式没什么不同。重要的是,当我们使用RegisterInstance方法时,Unity会注册一个单例。

我们还有一种方法可以把已经存在的实例注入到容器中。

             UnityContainer container = new UnityContainer();
             container.RegisterType<ILogger,FileLogger>();
             SQLDatabase existDatabase = new SQLDatabase();
             container.BuildUp(existDatabase);
             container.RegisterInstance<Database>(existDatabase);
             Database database = container.Resolve<Database>();

就如上边代码中,我们已经存在一个database 是DB2Database。你希望Unity做的是把依赖注入到容器中。

我们用BuildUp方法告诉Unity我们的想法。这时候Unity回去DB2Database 类,如果他发现了[Dependency]这个特性。他就自动的把我们前边注册的FileLogger注入到DB2Database的Logger字段中。

以下是DB2Database类:

public class DB2Database:Database
    {
        [Dependency]
        public ILogger Logger { get; set; }
    }

使用配置文件来实现关系映射

我们也可以再web.config里配置 文件的依赖关系映射。首先我打开web.config文件。按照如下结构添加section。这里我只是简单的映射了ILogger 接口和FileLogger。并且指定了生命周期是单例。

<configuration>
  <configSections>
    <section name="unity"
             type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <container name="containerOne">
      <types>
        <type type="UnityDemo_ConsoleApplication.ILogger" mapTo="UnityDemo_ConsoleApplication.FileLogger"
              lifeTime="Singleton"/>
      </types>

    </container>

  </unity>
...
...
</configuration>

如果你想更详细的了解元素和属性的使用,可以看以下Unity 在xml中配置的结构图:



更详细了解,请参见:

http://msdn.microsoft.com/en-us/library/ff647848.aspx

http://msdn.microsoft.com/zh-cn/library/dd203230.aspx

如何读取配置 并加载

Unity同样支持我们在配置文件里写设定映射关系。

首先我们要引入命名空间: Microsoft.Practices.Unity.Configuration;

在Unity2.0以上版本,已经废弃了以前的方法。现在我们有2种方式可以读取配置。

第一种,我们使用configurationManager:

引用命名空间:System.Configuration

            IUnityContainer myContainer = new UnityContainer();

            myContainer.LoadConfiguration("containerOne ");
            UnityConfigurationSection section
                = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            section.Configure(myContainer,"containerOne");

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读