Unity应用

0、Unity应用
 

0、Unity应用 1
1 1、控制倒转IoC(Inversion of Control) 2
1.1 工厂模式 2
2 2、依赖注入DI(Dependency Injection) 4
2.1 BuildUp手动注入 4
3 1、基础使用步骤 4
3.1 1、建立容器 4
3.2 2、将接口与类的映射注册到容器中 4
3.2.1 RegisterType 4
3.2.2 RegisterInstance(默认单例) 5
3.3 3、从容器中解析出正确的对象 5
3.4 BuildUp 方法 5
4 5、LifetimeManager对象生命周期 5
4.5 1.ContainerControlledLifetimeManager 5
4.5 2.ExternallyControlledLifetimeManager 5
4.5 3.PerThreadLifetimeManager 6
5 6、嵌套容器 6
6 8、杜绝循环引用 6
6.1 Constructor Injection构造器的参数中互相引用 6
6.2 Constructor Injection生成的对象作为自身构造器的参数 7
6.3 method call injection生成的对象互相引用 7
6.4 property(setter) injection生成的对象互相引用 7
7 9、容器vs.工厂 8
7.1 several reasons to use containers 8
7.2 Factory实例 9
7.3 使用容器不使用工厂的理由 11
8 10、Unity vs. MEF 11

1 1、控制倒转IoC(Inversion of Control)
1.1 工厂模式

UtopiaObjectFactory
using System;
using  System.Reflection;
using  System.Configuration;
namespace  UtopiaObjectFactory
{
   /// <summary>
   ///将创建的对象放入缓存中,
   ///用的时候检查缓存是否存在对象,
   ///没用则创建对象
   /// </summary>
   public sealed class  DataAccess
   {
      public  DataAccess()
      { }
      #region  CreateObject
     
      /// <summary>
      /// 创建对象,不使用缓存
      ///<appSettings>
      ///   <add  key="AProduct "  value="strPath,strClassCacheKey)" />
      ///</appSettings>
      /// </summary>
      public  static  object  CreateObjectNoCache(string path,string  CacheKey)
        
         try
         {
           object  objType =  Assembly.Load(path).CreateInstance(CacheKey);
           return  objType;
         }
  catch//(System.Exception ex)
         {
           //string  str=ex.Message;// 记录错误日志
           return null;
              
        
      }
      /// <summary>
      /// 创建对象或从缓存获取,使用缓存
      /// </summary>
      public static  object  CreateObject(string  path,string  CacheKey)
           
         object objType  DataCache.GetCache(CacheKey);
         if (objType ==  null)
         {
           try
           {
              objType =  Assembly.Load(path).CreateInstance(CacheKey);             
  DataCache.SetCache(CacheKey,  objType);// 写入缓存
           }
  catch//(System.Exception ex)
           {
              //string  str=ex.Message;// 记录错误日志
           }
         }
         return objType;
      }
      #endregion
   }
}
2 2、依赖注入DI(Dependency Injection)
2.1 BuildUp手动注入
BuildUp 常用的场景是:创建一个对象,然后调用  BuildUp 方法将其所需的 "零件"(依赖对象) 自动从配置文件或其他什么地方 "装配" 上。
3 4、基础使用步骤
3.1 1、建立容器
容器内已放入了要使用的Class,根据用户的请求返回一个Instance
工厂则要根据用户的请求从缓存中取出Instance或new一个Class
3.2 2、将接口与类的映射注册到容器中
3.2.1 RegisterType
1、RegisterType向Unity container中注册类型(registers a type ),可以是接口或是一个基类,在使用Resolve 方法获得对象时,dependency injection特性将其作用;默认情况下lifetime是短周期,每次使用 Resolve 方法都获得一个新对象;如果想使用单件的,可以这样:
container.RegisterType<CustomerService>(new  ContainerControlledLifetimeManager());
3.2.2 RegisterInstance(默认单例)
RegisterInstance则是注册实例 (instance),默认情况下每次使用 Resolve 方法都获得同一个对象,即单件模式;

3.3 3、从容器中解析出正确的对象
Resolve<T>()
3.4 BuildUp 方法
如果目标对象并非由容器实例化(非 Resolve 创建),那么依赖注入行为是不会发生的.
如果想让实例的dependency injection特性起作用,要使用BuildUp 方法

BuildUp 常用的场景是:创建一个对象,然后调用  BuildUp 方法将其所需的 "零件"(依赖对象) 自动从配置文件或其他什么地方 "装配" 上来。这对于开发可扩展可变更应用是非常有用的。
4 5、LifetimeManager对象生命周期
4.1 1.ContainerControlledLifetimeManager
Unity保存一个指向对象实例的引用。通过Unity容器为同一个类型或对象获取对象实例时,每次获取到的都是同一个实例。也就是说实现了对象单例模式。默认情况下,RegisterInstance方法使用该Lifetime  Manager。
4.2 2.ExternallyControlledLifetimeManager
只持有对象实例的弱引用(weak  reference),这意味着对象是可以被  GC 回收的.
某些时候,我们即希望对象能共用,同时又希望在不需要的时候被释放,以便空出更多的可用内存。

Unity仅保存一个指向对象实例的弱引用。通过Unity容器为同一个类型或对象获取对象实例时,每次获取到的都是同一个实例。
但是由于当对象创建完之后,容器没有对该对象的强引用,所以就可能出现当其他地方没有去强引用它时候,会被GC回收掉。
4.3 3.PerThreadLifetimeManager
同一个线程中连续两次获取到的是同一个Instance,而不同的线程中获取到的Instance不一样
5 6、嵌套容器
创建嵌套容器,子容器可以继承父容器的设置。通常情况下,我们会在程序启动点创建一个全局型的父容器,它包含了基本的全局类型注册。但由于它的生命周期过长,我们并不能很方便地管理所创建对象(比如说Singleton)的生命周期,此时创建一个随时可以被Dispose 掉的子容器就是一个比较好的主意。
可以使用子容器及时释放掉某个局部  Singleton 对象,同时依旧可以使用父容器的类型映射信息。
子容器的另外一个作用就是注册新的类型来代替父容器设置,这对于按需配置策略是非常有必要的。

6 8、杜绝循环引用
6.1 Constructor Injection构造器的参数中互相引用
public class Class1
{
    public  Class1(Class2  test2)
    {
        ..
    }
}

public class Class2
{
    public  Class2(Class1  test1) 
    {
       
    }
}
6.2 Constructor Injection生成的对象作为自身构造器的参数
public class Class1
{
    public Class1(Class1 test1)
  }
}
6.3 method call injection生成的对象互相引用
public class Class1
{
    [InjectionMethod]
    public void Method1()
    {
        Method2();
    }

    [InjectionMethod]
    public void Method2()
    {
        Method1();
    }
}
6.4 property(setter) injection生成的对象互相引用
public class Class1
{
    [Dependency]
    public string Propert1
    {
        get
        {
            return Propert2;
        }
    }

    [Dependency]
    public string Propert2
    {
        get
        {
            return Propert1;
        }
    }
}
7 9、容器vs.工厂
7.1 several reasons to use containers
There are several  reasons to use  containers in your  application  development.  Containers provide  the ability to wrap  vanilla objects with a  wealth of other  services. This allows  the objects to remain  ignorant about  certain infrastructure  and plumbing details,  like transactionality  and role-based  security. Oftentimes,  the client code does  not need to be  aware of the  container, so there is  no real dependency  on the container  itself.
These services can  be configured  declaratively,  meaning they can be  configured via some  external means,  including  GUIs, XML  files, property files,  or vanilla .NET-based  attributes.
Containers that have  cross-cutting  services are also  reusable across  applications. One  container can be  used to  configure  objects across  various applications  within an enterprise.  Many services that  can be applied  across an  enterprise  are low- level  infrastructure and  plumbing services.  These services can  be used across an  enterprise  without  the need to deeply  embed container-  specific code or logic  within an application.
7.2 Factory实例

UtopiaObjectFactory
using System;
using  System.Reflection;
using  System.Configuration;
namespace  UtopiaObjectFactory
{
   /// <summary>
   ///将创建的对象放入缓存中,
   ///用的时候检查缓存是否存在对象,
   ///没用则创建对象
   /// </summary>
   public sealed class  DataAccess
   {
      public  DataAccess()
      { }
      #region  CreateObject
     
      /// <summary>
      /// 创建对象,不使用缓存
      ///<appSettings>
      ///   <add  key="AProduct "  value="strPath,strClassCacheKey)" />
      ///</appSettings>
      /// </summary>
      public  static  object  CreateObjectNoCache(string path,string  CacheKey)
        
         try
         {
           object  objType =  Assembly.Load(path).CreateInstance(CacheKey);
           return  objType;
         }
  catch//(System.Exception ex)
         {
           //string  str=ex.Message;// 记录错误日志
           return null;
              
        
      }
      /// <summary>
      /// 创建对象或从缓存获取,使用缓存
      /// </summary>
      public static  object  CreateObject(string  path,string  CacheKey)
           
         object objType  DataCache.GetCache(CacheKey);
         if (objType ==  null)
         {
           try
           {
              objType =  Assembly.Load(path).CreateInstance(CacheKey);             
  DataCache.SetCache(CacheKey,  objType);// 写入缓存
           }
  catch//(System.Exception ex)
           {
              //string  str=ex.Message;// 记录错误日志
           }
         }
         return objType;
      }
      #endregion
   }
}
7.3 使用容器不使用工厂的理由
工厂在大部分时间里是非常有价值的,却不能跨越其它程序重用的,常常所有可用的创建选项在工厂实现中被硬编码,使得工厂自己没有扩展性。大部分时间,类调用工厂中的创建方法必需知道创建工厂的哪个子类。

在编译时,一个使用工厂创建的对象所有的依赖性对于工厂来说是清楚的。暂时忘记一会儿那不相干的.NET反射,在运行时,没有办法在那些被创建的对象中插入或者改变行为方式和那些被装配的依赖性。所有这些必需发生在设计时,或者至少要求重新编译。例如假设,一个工厂创建了类Foo的实例且类Foo的实例需要类Bar的一个实例,那么,工厂就必需知道如何重新得到类Bar的一个实例。工厂必需创建一个新的实例,或者即使是产生对另一个工厂的调用。
8 10、Unity vs. MEF
从表面上,MEF有点类似IoC容器,但MEF并不是IoC容器。在这一点上,很多人都很困惑。  Oren Eini在他的博客中指出,MEF实际上是个组合框架(composition framework),而且定位客户是“大的应用”,两者合一,即可理解MEF的本质。
组合框架和IoC容器在表面上看很相似,都是以自动化的方式管理应用的依赖性,但其区别则在于细节上。IoC容器很久以前就不仅仅是管理依赖性了,它们还负责对象的生命周期,对象代理,面向aspect,事件聚合,事务管理等等东西。但组合框架则着重于单一个目的:依赖管理。听上去组合框架好像所做极有限,但其实不是这样。光从依赖管理来说,IoC容器往往是静态的,不透明的,而MEF则使得依赖管理变成一个动态的,透明的过程。
MEF的第二个方面,其定位是“大的应用”,极其大的应用,其中第一个客户大概就是Visual Studio本身。M
EF提供的这些功能,
-不用装载程序集即可查询元数据
-可以静态地核实所有组件的依赖图和拒绝那些会造成系统处于不合法状态的组件
-契约适配器
-提供一套发现机制,用于定位和装载扩展
-允许附件元数据的标记设置,用于辅助查询和过滤  都是围绕着依赖管理这个主题的,但也大概来自Visual Studio是第一个客户的需求。因为Visual
Studio涉及的组件成千上万,需要这样的东西,MEF是设计来处理这样的场景的。 

原文地址:https://www.cnblogs.com/utopia/p/1556973.html