zoukankan      html  css  js  c++  java
  • 微软企业库4.1学习笔记(四十一)依赖注入模块Unity 简介

      模块Unity是一个轻量的、可扩展的依赖注入容器,支持构造函数注入、属性注入、方法调用注入。你可以用它创建企业库对象,也可以创建自定义的业务对象。Unity和企业库中的其他模块有一些不同点:

    •   你可以独立的使用Unity模块来实现依赖注入技术,不需要其他模块的辅助。
    •   Unity支持用配置文件来准备容器,也支持在运行的时候用代码动态注册依赖关系。
    •   Unity和企业库的核心库没有依赖关系。它包含了内置的配置信息读取方法,如果需要的话,这些配置信息也可以从企业库的配置中读取。

      

      本节包含下面的内容

    •   简介
    •   在应用中使用Unity
    •   典型的解决方案
    •   设计Unity的目的
    •   扩展和修改Unity模块
    •   部署和实施
    •   示例代码

      1 简介

      模块Unity是一个轻量的、可扩展的依赖注入容器,支持构造函数注入、属性注入、方法调用注入。它为开发者提供了下面的好处:

    •   支持简单的创建对象,尤其是对于有继承关系和依赖关系的对象,简化了应用在这方面的代码。
    •   支持抽象的需求,允许开发者在配置中或者是在运行的时候指定依赖关系。
    •   通过拖延组建配置到容器中,增加了灵活性。
    •   具有服务定位的能力。允许客户端存储或者是缓存容器。这尤其在ASP.NET应用中有用,开发者可以将容器持久到Session或者是Application中。

      包含下面的一些话题,通过这些话题,你可以看看Unity模块是否适合于你。

    •   常用的解决方案
    •   示例代码
    •   Unity模块的亮点
    •   什么时候该用Unity模块

      1.1 常用解决方案

      Unity模块解决了一些开发者在基于组建开发的过程中遇到的问题。现代的商业应用,为了满足特殊的需求,都包含有自定义的业务对象和自定义的组件。组件还可能独立的实现横跨日志、验证、授权、缓存和异常处理的需求。

      成功构建这种类型应用的关键是完成一个解耦的、松散耦合的设计。松散耦合的应用更灵活、更容易维护。而且在开发的过程中更容易测试。你可以在测试的过程中伪造一些具有强依赖的对象,来辅助测试。例如:数据库连接、网络连接、ERP连接、富UI组件。

      依赖注入是构建松散耦合应用的首选技术。它提供了处理对象之间的依赖关系的方法。例如:一个处理客户信息的对象,可能会依赖于数据访问对象,验证信息的对象,检查用户是否被授权用户。依赖注入技术可以保证客户类被正确的初始化,并且加载上面所需的对象,尤其是当依赖于抽象的时候。

      下面的模式都是用来架构和简化这个开发过程的;

    •   Inversion of Control (IOC)pattern:反转控制模式,这个模式支持插件式的架构,对象可以在需要的时候,查询它所需的其他对象。
    •   Dependency Injection(DI) pattern:依赖注入模式,这个模式是IOC的一种特殊应用,是一种不改变类接口的前提下修改类行为的接口编程技术。开发者面向接口编程,使用容器在类中注入依赖对象的实例。注入对象的实例的技术是接口注入、构造函数注入、属性注入setter和方法调用注入。
    •   Interception pattern:拦截模式,这个模式引入了另一个层次的间接性。在客户端和真实对象之间建立一个对象,一个代理在客户端和真是对象之间。客户端操作真实对象的行为,被代理拦截,通过代理来完成他们之间的交互。

      Unity模块的使用步骤:

    •   建立Unity容器
    •   获取指定类型的对象
    •   获取指定类型和注册名称的对象
    •   获取一个特殊类型的所有对象
    •   使用BuildUp创建一个容器没有创建的对象
    •   注释对象为构造函数注入
    •   注释对象为属性注入
    •   注释对象为方法调用注入

      1.2 示例代码

      使用依赖注入框架和反转控制技术,开发者可以创建程序集中的自定义类的实例和依赖对象的实例。Unity支持这个功能,使得开发者可以容器配置注入、构造函数注入、属性注入、方法调用注入技术创建对象和依赖对象的实例。

      Unity提供了两个方法了来注册类型和映射他们的关系:

    •   RegisterType。这个方法在容器中注册一个类型,在适当的时候容器创建一个指定类型的实例。发生在通过类attribute初始化依赖注入和调用Resolve方法的时候。对象的声明周期可以在RegisterType方法中指定,如果没有指定,生命周期将是短暂的,意味着每次调用Resolve都会创建一个新的实例。

      容器配置注册类型

      

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Microsoft.Practices.Unity;

    namespace BeautyCode.Web.Unity
    {
        
    public interface IMyService
        { }
        
    public class CustomService : IMyService
        { }
        
    public class UnityDemo
        {
            
    public UnityDemo()
            {
                IUnityContainer ucontainer 
    = new UnityContainer();
                ucontainer.RegisterType
    <IMyService, CustomService>();

                IMyService myService 
    = ucontainer.Resolve<IMyService>();
            }
        }
    }
    •   RgisterInstance。这个方法用来注册一个已经存在的对象实例,同时指定生命周期。容器在生命周期之内返回这个已经存在的对象。如果没有指定生命周期,生命周期将由容器来管理。

      容器配置注册一个已经存在的对象实例

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Microsoft.Practices.Unity;

    namespace BeautyCode.Web.Unity
    {
        
    public interface IMyService
        { }
        
    public class LogService : IMyService
        { }
        
    public class UnityDemo
        {
            
    public void UnityDemo1()
            {
                IUnityContainer uContainer 
    = new UnityContainer();
                LogService myExistingObject 
    = new LogService();
                uContainer.RegisterInstance
    <IMyService>(myExistingObject);
                IMyService myServiceInstance 
    = uContainer.Resolve<IMyService>();
            }
        }

    }

      构造函数注入

      如果开发者使用Unity容器的Resolve方法实例化的一个类,这个类包含一个构造函数,构造函数对另外的一个对象有依赖。Unity容器会自动创建构造函数以来的对象。

      

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Microsoft.Practices.Unity;

    namespace BeautyCode.Web.Unity
    {
        
    public interface IMyService
        { }
        
    public class CustomService : IMyService
        {
            
    public CustomService(LogService log)
            {
                log.WriteLog(
    "loginfo");
            }
        }
        
    public class LogService : IMyService
        {
            
    public void WriteLog(string logMsg)
            { }
        }
        
    public class UnityDemo
        {
            
    public UnityDemo()
            {
                IUnityContainer ucontainer 
    = new UnityContainer();
                ucontainer.RegisterType
    <IMyService, CustomService>();
                ucontainer.RegisterType
    <IMyService, LogService>();

                CustomService  myService 
    = ucontainer.Resolve<CustomService >();
            }
        }

    }

      在运行的时候,开发者通过Resolve方法创建了一个CustomService类的实例,导致容器自动创建一个LogService对象,对象的范围是CustomService范围内。

      属性注入

      除了使用构造函数注入,Unity还支持属性注入和方法调用注入。下面的代码演示了属性注入。

     public class SupplierData
        {
            
    public string Name { getset; }
        }
        
    public class ProductService
        {
            
    private SupplierData _supplier;

            [Dependency]
            
    public SupplierData Supplier
            {
                
    get { return _supplier; }
                
    set { _supplier = value; }
            }

        }

      

      这时候创建一个ProductService类的实例,会自动创建一个SupplierData实例,作为ProductService实例的属性SupplierData的值。

      1.3 设计亮点

      Unity模块具有下面的功能:

    •   提供了一个创建对象的方法,也可能包括依赖的其他对象。
    •   提供了RegisterType方法,可以在容器中注册类型和映射关系,用Resolve方法可以返回对象的实例。
    •   通过提供的预先配置注入对象,实现了反转控制。你可以在构造函数中指定一个接口或者是类,你也可以在属性或者是方法上添加attribute实现注入。
    •   支持容器的继承。一个容器可以包含子容器,对象可以从子容器传递到父容器。
    •   可以从标准的配置系统中读取配置信息,例如xml文件,用它来配置容器。  
    •   对类的定义没有要求。在类上不用使用attribute(除非你使用属性注入和方法调用注入),在类声明中也没有要求。
    •   支持对容器的扩展,你可以实现自己的容器,支持额外的对象构造,和其他的容器功能,例如缓存等。

      

      1.4什么时候选用Unity模块

      

       依赖注入提供了简化代码、抽象对象之间的依赖、自动创建依赖对象的实例等机会。但是,过程还是会对性能有一点影响,在简化依赖的基础上还是增加了一点复杂性。

      通常情况下,你可以在下面的情形中使用Unity模块:

    •   你的对象和类对于其他对象和类有依赖关系。
    •   你的依赖关系复杂,需要抽象。
    •   你想要使用构造函数注入、属性注入和方法调用注入技术。
    •   你想要管理对象的生命周期。
    •   你想要在代码运行的时候配置和管理对象之间的依赖关系。
    •   你想要在Web应用中缓存和持久化依赖关系。

      在下面的情况,就不需要使用Unity模块了:

    •   你的对象和类对其他对象和类没有依赖。
    •   你的依赖关系简单,不需要抽象。

     Unity 容器使用顺序图

      

     

  • 相关阅读:
    把Chrome浏览器变成文本编辑器
    pigcms 标签读不出
    全排列函数
    线性基(二
    线性基(一
    fabs() abs()
    字面量声明的函数,后边最好加一个分号,否则的话,在控制台执行有问题的
    mongo集群
    linux的查找命令
    mysql 解决Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’错误
  • 原文地址:https://www.cnblogs.com/DoNetCShap/p/2295521.html
Copyright © 2011-2022 走看看