天天看点

DNN模块开发中自定义Data Provider加载方法

NET反射工厂方法

数据提供者应用程序接口DataProvider不仅是抽象数据库访问基类同时也是实例化具体数据库的工厂。它提供了实例化具体数据库访问对象的工厂方法。DataProvider中的工厂方法是静态过程Static viod CreateProvider()。这个工厂方法调用反射类中的CreateObject函数动态的生成实例对象。CreateObject有如下两种重载形式:

1.DotNetNuke.Framework.Reflection.CreateObject(“data”);

2.DotNetNuke.Framework.Reflection.CreateObject(“data”,”Cross.DNN.Modules.CrossArticle.Data”, “Cross.DNN.Modules.CrossArticle”));

实现反射的关键是要提供所要创建实例的类型名称。类型名称(TypeName)由两部分组成,第一部分是包含了完整名称空间(namespace)的类名,第二部分是类所在的组件(Assembly)的名称。上面的两种重载形式对应着两种获得类型名称的方法。

由于采用反射技术在运行时才知道要所要实例化的相关信息,因此这些信息不可以固化在程序中。DNN所采用的是在配置文件(web.config)中定义了数据提供者应用程序接口实现的配置信息,并提取这些信息到相应的类中。配置文件中针对不同的提供者模式定义了相应的节(section),如数据提供者模式所对应的节就是”data”。以下呈现的就是配置文件中”data”节的相关信息:

1.Section Handle:<section name=”data” type=”DotNetNuke.Framework.Providers.ProviderConfigurationHandler, DotNetNuke” />;

2.Section:

<data defaultProvider=”SqlDataProvider”>

      <providers>

        <clear />

        <add name=”SqlDataProvider” type=”DotNetNuke.Data.SqlDataProvider, DotNetNuke.SqlDataProvider” connectionStringName=”SiteSqlServer” upgradeConnectionString=”” providerPath=”~/Providers/DataProviders/SqlDataProvider/” objectQualifier=”” databaseOwner=”dbo” />

      </providers>

</data>

Section Handle的作用一是标明了具体配置节(section)的名称;二是在type属性中提供了提取配置信息对象的类型名称,即位于DotNetNuke.Framework.Providers 名称空间下的ProviderConfigurationHandler 类,它所属于的组件名称是DotNetNuke 。该类实现了IconfigurationSectionHandler接口返回ProviderConfiguration 对象,ProviderConfiguration 类中有两个重要的属性:DefaultProvider和Providers属性,即对应着data节中的内容。其中DefaultProvider属性的类型是字符串,存储了<data>节defaultProvider属性值;Providers属性的类型是哈希表(hashtable),存储了<providers>下子节<add>的信息,hashtable的数据结构是名/值对,其名称对应着<add>节属性name的值,值则对应着<add>节所有属性名/值对构成的属性集合即XmlAttributeCollection数据类型。这个类型的对象是作为Provider类构造函数的参数实例化Provider对象的。Provider对象提供了三个属性:Name,Type,Attributes分别对应着<add>节中的name属性值,type属性值,以及其它属性名/值对构成的集合即NameValueCollection对象。具体的数据库访问类就是通过Provider类的Attributes属性获得数据库信息的。

在Reflection类中用第一种方法生成对象时,首先将参数”data”传递给函数ConfigurationSettings.GetConfig,这个.NET自带的静态函数根据参数”data”在web.config中定位到相应的Section Handle并调用这个Section Handle返回ProviderConfiguration对象objProviderConfiguration。然后将objProviderConfiguration.Providers(objProviderConfiguration.DefaultProvider)作为构造函数的参数实例化一个Provider对象。所要生成的对象的类型名称即由Provider对象的Type属性提供。

第二种方法获得ProviderConfiguration对象的过程和第一种方法相同。然后将第二和第三个参数分别加上后缀字符串ProviderConfiguration对象的DefaultProvider属性值构成所要生成的对象的类型名称。这种方法用于实例化DNN模块的具体数据库访问类。由于DNN模块可由第三方开发,模块的名称空间和组件名称等可以自定义,不可能针对每一个自定义模块都在web.config中定义与其相关的配置信息。因此采用第二种方法,只要把自定义的名称空间和组件名称作为参数传递给反射工厂方法即可得到需要实例化的类型名称。而DNN系统的核心功能模块则采用第一种方法。

Reflection类除了从配置文件 提取信息获得类型名称并创建相应的实例外,还将这个实例放入缓存Cache中以提高系统性能。如果不采用反射技术,只使用一般的工厂方法。当新增一个数据库类型时就要新增一个具体工厂,从而需要重新编译主程序,降低了应用程序的可维护性。

继续阅读