代码改变世界

微软企业库4.1学习笔记(六)创建对象

2010-04-15 07:09  Virus-BeautyCode  阅读(5285)  评论(6编辑  收藏  举报

  一、创建应用模块对象

  在你的应用中经常会需要创建例如Database或者是CacheManager之类的对象,企业库支持一系列的方法,可以创建应用需要的对象。

  你可以使用工厂方法创建这些对象,企业库的在每一个功能模块和核心库都包含有工厂方法来完成这个任务。这些静态的工厂方法自动读取应用的配置信息,provider的工厂方法允许你手工在配置文件中创建适当的配置,然后用工厂方法在代码中创建provider。

  还有,你也可以创建配置信息中没有描述的对象。例如,通过在构造函数中添加数据库连接信息,你可以创建一个SqlDatabase对象。

  另外,企业库4.1还包含了一个轻量的、可以扩展的,支持构造函数、属性、方法调用注入的依赖注入容器,Unity模块。

  下面将介绍使用不同的方法创建对象:

  •   使用静态方法创建对象
  •   使用Provider的工厂方法创建对象
  •   使用Unity创建对象
  •   直接使用构造函数创建对象

  Tooltip:使用Unity除了可以创建企业库对象之外,还可以创建自定义的业务对象。

  1、使用静态方法创建对象

  企业库的静态方法实现了工厂模式,如果使用这些工厂方法创建对象,意味着你不需要实现任何创建对象所需的provider信息。

  下图显示了核心库如何创建对象

  

 

  下面的代码示例了使用Data Access模块的DatabaseFactory方法创建Database对象

 

    Database db=DatabaseFactory.CreateDatabase("Northwind");
  

 

  Database是一个抽象类,定义了为实现provider定义了常用的接口。静态方法CreateDatabase返回一个在provider中描述的对象(例如SqlDatabase),对象的类型由配置信息决定。

  静态的工厂方法使用默认配置源中的配置信息,你可以通过命令行制定默认的配置源。如果你没有定义配置源,静态方法将使用系统配置源,这就意味着你的配置信息必须要存储在应用的app.config和web.config文件中。

  

代码
<enterpriseLibrary.ConfigurationSource selectedSource="systemSource">
   <sources>
     <add name="fileSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common" filePath="test.exe.config"/>
     <add name="systemSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SystemConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common"/>
   </sources> 
</enterpriseLibrary.ConfigurationSource>

 

  在上面的xml中显示了一段定义在应用配置文件中的配置节,里面定义了两个配置源。一个对应文件test.exe.config,一个就是系统配置源。

  关于配种源使用的一些注意点:

  •   静态方法使用配置文件来决定默认的配置源,这就意味着你在使用静态方法的时候必须有一个应用的配置文件。
  •   如果你的配置文件不包含</enterpriseLibrary.ConfigurationSource>配置节,企业库将会使用系统配置源,这就意味着你必须将配置信息直接存储在你的配置文件中,而不是放在配置节定义的配置源中。
  •   所有的静态方法都是用默认的配置源,意味着创建所有模块对象所需要的配置信息都放在同一个位置。

  2、使用provider的工厂方法创建对象

  首先用一个静态方法创建适当的配置源对象,然后构造一个provider对象。你也可以在应用中使用provider的工厂方法创建对象。

  使用provider的工厂方法创建对象,需要完成下面的几步:

  1)创建配置源对象

  2)利用配置源对象,创建provider工厂对象

  3)使用provider工厂对象创建provider

   2.1创建配置源

  可以使用ConfigurationSourceFactory类创建配置源对象,Create方法接受一个参数,参数是配置源的名称。这个配置源一定要先在应用的配置文件中定义,如果没有定义会抛出异常。意味着你如果使用ConfigurationSourceFactory,应用程序必须要有一个配置文件。下面的代码显示了使用ConfigurationSourceFactory类创建配置源对象。

  

IConfigurationSource source = ConfigurationSourceFactory.Create("fileSource");
  

 

  你也可以直接构造配置源对象,构造函数需要配置源的信息。

  

FileConfigurationSource fileSource = new FileConfigurationSource(@"ProductApplication.config"); 
 
SystemConfigurationSource systemSource = new SystemConfigurationSource();
    

  Tooltip:企业库包括一个SqlConfigurationSource配置源provider的例子。使用Data Access读取存放在SQL server数据库的配置信息,这个provider使用的配置节需要继承自SerializableConfigurationSection类。具体的可以参考企业库中的SqlConfiguration QuickStart。

  

   配置更新的通知

  所有的配置源类都实现了IconfigurationSource接口,接口定义如下,从下面的定义可以看出,可以使用代码来描述配置源的改变。

通过实现 void AddSectionChangeHandler(string sectionName, ConfigurationChangedEventHandler handler);
void RemoveSectionChangeHandler(string sectionName, ConfigurationChangedEventHandler handler);方法就可以实现更新通知。在企业库中只要Logging模块注册为接受通知。

  

 

代码
public interface IConfigurationSource
{
    
// Methods
    void Add(IConfigurationParameter saveParameter, string sectionName, ConfigurationSection configurationSection);
    
void AddSectionChangeHandler(string sectionName, ConfigurationChangedEventHandler handler);
    ConfigurationSection GetSection(
string sectionName);
    
void Remove(IConfigurationParameter removeParameter, string sectionName);
    
void RemoveSectionChangeHandler(string sectionName, ConfigurationChangedEventHandler handler);
}

 

 

 

  2.1创建provider工厂

  provider的构造函数参数是configurationsource对象,provider工厂对象使用这个configurationsource为provider对象读取配置信息。

  

 


            SystemConfigurationSource systemSource 
= new SystemConfigurationSource();
            DatabaseProviderFactory providerFactory 
= new DatabaseProviderFactory(systemSource);

 

  2.2使用provider工厂创建provider

  你可以使用一个provider工厂构造多个provider实现,你也可以使用从多个配置源创建的多个provider工厂对象创建应用的对象。

  下面的代码显示了如何从不同的配置源创建两个DatabaseProviderFactory。DatabaseProviderFactory对象factory1从ProductApplication.config文件中读取配置信息,DatabaseProviderFactory对象factory2从应用的配置文件中读取配置信息。

  

 

 

代码
 FileConfigurationSource fileSource=new FileConfigurationSource(@"c:\productapplication.config");
            DatabaseProviderFactory factory1
=new DatabaseProviderFactory(fileSource );
            Database db1
=factory1.CreateDefault ();

            SystemConfigurationSource systemSource 
= new SystemConfigurationSource();
            DatabaseProviderFactory factory2 
= new DatabaseProviderFactory(systemSource);
            Database db2
=factory2.Create("northwind");

 

  使用要点:

  一个provider工厂对象只能绑定一个配置源对象,在你构造了provider工厂之后不能改变这个providerfactory的配置源。

  3、使用Unity创建对象

  Unity模块给开发者开发业务对象和服务接口,以及组织和架构应用提供了一个新的方式。在写代码和企业库进行相互配合的情况下,也提供了一种新的方式。在4.1版本的企业库中,你可以使用Unity提供的依赖注入容器创建企业库对象和你的业务对象。

 

    这个新功能对现有代码没有影响,企业库做了大量工作,来保证对已有代码和应用的兼容性。但是,如果开发新应用,Unity是推荐的方式,尽管没有强迫开发者使用。

  3.1关于Unity模块

  Unity模块实现了一个叫做UnityContainer的容器,暴露了一些方法,包括用来注册接口(或者是基类,或者是抽象类)和实现类(包括实例和singleton类型)之间映射关系,获取对象实例,使用依赖对象建立已有的对象。Resolve和BuildUp方法返回的实例,是在容器中注册的类型基础上的适当的依赖对象实例。你也可以创建一个有等级的嵌套的容器,自己管理对象和容器的生命周期。

  

 

代码
public interface IUnityContainer : IDisposable
{
    
// Methods
    IUnityContainer AddExtension(UnityContainerExtension extension);
    IUnityContainer AddNewExtension
<TExtension>() where TExtension: UnityContainerExtension, new();
    T BuildUp
<T>(T existing);
    T BuildUp
<T>(T existing, string name);
    
object BuildUp(Type t, object existing);
    
object BuildUp(Type t, object existing, string name);
    TConfigurator Configure
<TConfigurator>() where TConfigurator: IUnityContainerExtensionConfigurator;
    
object Configure(Type configurationInterface);
    IUnityContainer CreateChildContainer();
    IUnityContainer RegisterInstance
<TInterface>(TInterface instance);
    IUnityContainer RegisterInstance
<TInterface>(string name, TInterface instance);
    IUnityContainer RegisterInstance(Type t, 
object instance);
    IUnityContainer RegisterInstance
<TInterface>(TInterface instance, LifetimeManager lifetimeManager);
    IUnityContainer RegisterInstance
<TInterface>(string name, TInterface instance, LifetimeManager lifetimeManager);
    IUnityContainer RegisterInstance(Type t, 
object instance, LifetimeManager lifetimeManager);
    IUnityContainer RegisterInstance(Type t, 
string name, object instance);
    IUnityContainer RegisterInstance(Type t, 
string name, object instance, LifetimeManager lifetime);
    IUnityContainer RegisterType
<T>(params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType
<TFrom, TTo>(params InjectionMember[] injectionMembers) where TTo: TFrom;
    IUnityContainer RegisterType
<T>(LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType
<TFrom, TTo>(LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers) where TTo: TFrom;
    IUnityContainer RegisterType
<T>(string name, params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType
<TFrom, TTo>(string name, params InjectionMember[] injectionMembers) where TTo: TFrom;
    IUnityContainer RegisterType(Type t, 
params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType
<T>(string name, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType
<TFrom, TTo>(string name, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers) where TTo: TFrom;
    IUnityContainer RegisterType(Type t, LifetimeManager lifetimeManager, 
params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType(Type t, 
string name, params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType(Type from, Type to, 
params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType(Type t, 
string name, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType(Type from, Type to, LifetimeManager lifetimeManager, 
params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType(Type from, Type to, 
string name, params InjectionMember[] injectionMembers);
    IUnityContainer RegisterType(Type from, Type to, 
string name, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers);
    IUnityContainer RemoveAllExtensions();
    T Resolve
<T>();
    T Resolve
<T>(string name);
    
object Resolve(Type t);
    
object Resolve(Type t, string name);
    IEnumerable
<T> ResolveAll<T>();
    IEnumerable
<object> ResolveAll(Type t);
    
void Teardown(object o);

    
// Properties
    IUnityContainer Parent { get; }
}

 

  Unity模块不是自动读取配置信息来创建对象和配置容器。提供了最大的灵活性,你可以用代码初始化一个Unity容器,然后初始化注册信息,类型映射, 以及扩展信息。这些都会定义在你创建一个容器的时候加载的配置信息中,你也可以在加载之后使用容器提供的方法修改它们。

  你可以将配置信息放在app.config或者web.config文件中,你也可以使用自定义的配置文件或者是自定义的配置源。

  在4.1版本的企业库,如果你将Unity的配置信息放在应用的配置文件中(app.config和web.config),你需要手动配置Unity的相关信息。具体的配置可以看Unity Application Block  Documentation。

  下面的表格列出一些Unity容器的方法,通过这些方法可以返回一个适当的企业库对象。

Method signature Description
Resolve<T>() 返回一个在配置中定义的默认对象实例的实现类,类型是泛型指定类型
Resolve<T>(string name) 返回一个在配置中定义的指定名称的对象实例的实现类,类型是泛型指定类型
Resolve(Type t) 返回一个在配置中定义的默认对象实例的实现类,类型通过参数指定
Resolve(Type t, string name) 返回一个在配置中定义的返回一个在配置中定义的默认对象实例的实现类,类型通过参数指定
 

  未完待续。。。。。。。。。。。。。。。。