65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 .NET Enterprise Library 创建自定义应用程序块

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2009 年 9 月 28 日

CPOL

7分钟阅读

viewsIcon

38988

downloadIcon

324

本白皮书旨在帮助开发人员使用 .NET Enterprise Library 创建自定义应用程序块。

目录

  1. 引言
  2. 必备组件
  3. .NET Enterprise Library 2.0 命名空间
  4. 技术设计规范
  5. 创建自定义应用程序块
  6. Page_Load
  7. 构建 Web.config 文件
  8. 为类库 DLL 生成公钥令牌
  9. 参考
  10. 结论

引言

我曾从事 spring.NET 框架的工作,并且长期以来一直深入研究 .NET Enterprise Library。每次使用这些框架时,我都会感受到它们之间强烈的相似性。随着时间的推移,微软几乎涵盖了 spring.net 框架通常为开发人员提供的 .NET Framework 中的所有内容。我只能说,微软紧跟最新技术,并希望与时俱进。正是 spring.NET 给了主页的概念和演变,同样,我们也有自定义应用程序块,它体现了依赖注入和面向切面编程的思想。在这里,我将不描述 spring .NET 和 .NET Enterprise Library 的相似之处或区别。我的目的是帮助开发人员使用 .NET Enterprise Library 实现和开发自定义应用程序块。网上可能有各种文章,但我希望在本课程的这一部分展示我的发现。我们都知道依赖注入设计模式,它已不再是新话题。简而言之,依赖注入通过对象的构造函数隔离对象的实现,并在运行时调用和创建对象,从而允许以最简单、最松耦合的方式灵活操作。它是控制反转模式的一种形式,其中工厂对象负责对象创建、链接和加载,进而形成运行时对象创建和调用的实例化。

我在这里将展示如何使用 .NET Enterprise Library 创建自定义应用程序块,它能够很好地演示依赖注入的概念。所有类和命名空间都将在配置文件中配置,从而在运行时链接和加载。这是一种需求调用方法。

自定义应用程序块

这种方法最好的地方在于,我们可以在同一个环境中测试和开发同一个项目集下的模块。更广泛地说,我们可以配置自定义应用程序块,以便测试人员可以在同一台机器上测试应用程序,而开发人员则可以在同一台机器上修复或开发。

例如:我有一个 fileUploaderModule 包,为了让我的团队的生活更轻松,我会怎么做?我会创建两个包,一个包是 fileUploaderModule_test ,另一个包是 fileUploaderModule_Dev ,并在配置文件中配置它们,这将帮助测试人员和开发人员在同一工作包上并行工作。这样我就能节省应用程序额外的测试服务器。这种方法将帮助我在同一台机器上为两个角色进行测试和开发。

拥有这种设计设计的另一个用途是利用组织中跨项目/应用程序的基于能力的资产,从而提高生产力,因为它可以在开发级别上作为全局功能需求使用。

例如,我有一个被组织中 10 个应用程序使用的登录机制。在这种情况下,我将开发一个登录自定义应用程序块,该应用程序块将由 10 个跨应用程序使用,使该块成为一个独立的实体并充当服务提供商。

在考虑了上述措施后,我们得出结论,在设计方面我们将获得以下优势。

  • 松耦合架构
  • 可作为库跨项目重用
  • 易于测试,因为它是自定义打包设计
  • 易于维护
  • 易于部署,因为自定义打包可在配置文件中配置

问题陈述:我需要通过文件传输系统端口将文件上传到服务器。因此,这里的挑战在于,服务器详细信息必须是可配置的,因为该服务器将来可能会更改。此外,此包应开发成可供不同应用程序使用,并具有易于插入的功能。

必备组件

  • .NET Framework 2.0
  • Enterprise Library 2.0

.NET Enterprise Library 2.0 命名空间

  • Microsoft.Practices.EnterpriseLibrary.Common.dll
  • Microsoft.Practices.ObjectBuilder.dll

技术设计规范

在这里,我将演示默认设置配置块和特定设置配置块部分。它的工作方式类似于默认构造函数和参数化构造函数。如果我们不提供提供程序名称,则它会选择默认设置,否则它会根据提供程序名称选择设置。为了更直观和易于理解,请参阅顺序图和红色文本。

图 1.0 顺序图:默认设置

<dbConfiguration defaultDBProvider="DefaultFilePath">
    <dbProviders>
	<add name="DefaultFilePath" 
	type="Project.Practice.DB.DBProvider,Project.Practice.DB" userID="admin"
	password="admin" server="militaryZoneArea" database="xyz"/>	
</dbConfiguration>
DefaultDB.JPG - Click to enlarge image

图 2.0 顺序图:自定义设置

<add name="CustomFilePath" 
	type="Project.Practice.DB.DBProvider,Project.Practice.DB" userID="admin" 
	password="admin" server="militaryZoneArea" database="xyz"/>
</dbProviders>
CustomDB.JPG - Click to enlarge image

创建自定义应用程序块

让我们深入研究代码以获得更多理解。我们创建 DBAssembler ,它实现了 IAssembler。这是我们使用可配置的 DBdata 设置详细信息创建 DbProvider 对象的终结点。在完整的往返过程中,会创建 DBProvider 对象并调用 UploadFile() 方法。

设计配置提供程序

DBAssembler.cs
public class DBAssembler : IAssembler <IDBProvider, DBData>
{
    public IDBProvider Assemble
		(Microsoft.Practices.ObjectBuilder.IBuilderContext context, 
                	 DBData dbData, IConfigurationSource configurationSource, 
                  	 ConfigurationReflectionCache reflectionCache)
   {
        return new DBProvider(dbData.UserId, dbData.Password, 
				dbData.Server, dbData.Database);
    }
} 
DBData.cs

此类是所有配置设置的容器对象。

[Assembler(typeof(DBAssembler))]
    public class DBData : NameTypeConfigurationElement
    {
        private const string userIdProperty = "userID";
        private const string passwordProperty = "password";
        private const string serverProperty = "server";
        private const string databaseProperty = "database";

        public DBData()
            : base("DBData", typeof(IDBProvider))
        {
        }
        public DBData(string name, Type type)
            : base(name, type)
        {
        }

        [ConfigurationProperty(userIdProperty, IsRequired = true)]
        public string UserId
        {
            get { return (string)this[userIdProperty]; }
            set { this[userIdProperty] = value; }
        }

        [ConfigurationProperty(passwordProperty, IsRequired = true)]
        public string Password
        {
            get { return (string)this[passwordProperty]; }
            set { this[passwordProperty] = value; }
        }

        [ConfigurationProperty(serverProperty, IsRequired = true)]
        public string Server
        {
            get { return (string)this[serverProperty]; }
            set { this[serverProperty] = value; }
        }

        [ConfigurationProperty(databaseProperty, IsRequired = false)]
        public string Database
        {
            get { return (string)this[databaseProperty]; }
            set { this[databaseProperty] = value; }
        }
    }
DBDataRetriever.cs

编写 DBretriever 是为了能够根据调用链接和加载默认配置节。

 internal class DBDataRetriever : IConfigurationNameMapper
    {
        public string MapName(string name, IConfigurationSource configurationSource)
        {
            return string.IsNullOrEmpty(name) == false ? 
            name : ((DBSettings)configurationSource.GetSection(DBSettings.SectionName)).
		DefaultDBProvider;
        }
    }
DBSettings.cs
public class DBSettings : SerializableConfigurationSection
{
    public const string SectionName = "dbConfiguration";
    private const string DBProvidersProviderProperty = "dbProviders";
    private const string DefaultDBProviderProperty = "defaultDBProvider";
    public DBSettings() { }
    
    [ConfigurationProperty(DBProvidersProviderProperty, IsRequired = true)]
    public NameTypeConfigurationElementCollection <DBData> DBProviders
    {
        get { return (NameTypeConfigurationElementCollection 
			<DBData>)base[DBProvidersProviderProperty]; }
    }
    
    [ConfigurationProperty(DefaultDBProviderProperty, IsRequired = true)]
    public string DefaultDBProvider
    {
        get { return (string)base[DefaultDBProviderProperty]; }
    }
}

设计工厂和提供程序类

DBFactory.cs

DBFactory 是创建 DBProviderFactory 的类,之后当调用默认设置时,它会发挥重要作用,并调用 CreateDefault() 来继续承担责任,或者调用 Create() 来处理自定义设置调用。有关详细信息,请参阅顺序图。

public static class DBFactory
{
    public static IDBProvider CreateProvider()
    {
        try
        {
            DBProviderFactory factory = 
		new DBProviderFactory(ConfigurationSourceFactory.Create());
            return factory.CreateDefault();
        }
        catch (ConfigurationErrorsException configurationException)
        {
            throw;
        }
    }
     public static IDBProvider CreateProvider( string name )
    {
    try
    {
        DBProviderFactory factory = 
		new DBProviderFactory( ConfigurationSourceFactory.Create() );
        return factory.Create( name );
    }
    catch( ConfigurationErrorsException configurationException )
    {
        throw;
    }
 }
}
DBCustomFactory.cs

通过查看顺序图可以最好地解释和理解这一点。基本上,当未调用默认设置时,会调用 DBCustomfactory DBCustomFactory 获取所有配置并将它们设置在 DBData 中,然后将 DBData 返回给 DBassembler

public class DBCustomFactory : AssemblerBasedCustomFactory <IDBProvider, DBData>
{
    protected override DBData GetConfiguration
	(string name, IConfigurationSource configurationSource)
    {
        DBSettings settings = 
	(DBSettings)configurationSource.GetSection(DBSettings.SectionName);
        return settings.DBProviders.Get(name);
    }
}
DBProvider.cs

DBProvider 实现了 IDBProvider 并设置在config文件中配置的值。在构造函数中设置值的责任由 DBsetting 类承担。

[ConfigurationElementType(typeof(DBData))]
public class DBProvider : IDBProvider
{
    protected string m_UserId = string.Empty;
    protected string m_Password = string.Empty;
    protected string m_Server = string.Empty;
    protected string m_DirectoryPath = string.Empty;
    
    private bool m_Disposed = false;
    
    public DBProvider() { }
    public DBProvider
	(string userId, string password, string server, string directoryPath)
    {
        m_UserId    = userId;
        m_Password  = password;
        m_Server    = server;
        m_DirectoryPath = directoryPath;
    }
    
    #region IFTPProvider Interface
    
    bool IDBProvider.UploadFile(string filePath)
    {
        //The functionality is not given here..
        //Intension here is one can make use of these configurable credential
        //Connect to FTP and transfer file.
        //OpenFTP(m_Server,m_UserId,m_Password,m_DirectoryPath,
        //filePath,domain,port) 
        return true;
    }
 }
DBProviderFactory.cs
public class DBProviderFactory : NameTypeFactoryBase <IDBProvider>
{
    protected DBProviderFactory()
        : base()
    {
    }
    
    public DBProviderFactory(IConfigurationSource configurationSource)
        : base(configurationSource)
    { }
}
IDBProvider.cs

IDBProvider 基本上存储了自定义属性的集合,我们在其中声明了默认和自定义设置类。它还公开了可供客户端接口使用的方法列表。

[ConfigurationNameMapper(typeof(DBDataRetriever))] 
[CustomFactory(typeof(DBCustomFactory))]
public interface IDBProvider : IDisposable
{
    bool UploadFile(string filePath );
}

Page_Load

这是调用运行时对象实例的入口点,在此,工厂对象负责对象创建。因此,DBFactory.CreateProvider() 用于默认设置,而 DBFactory.CreateProvider("CustomFilePath")) 用于自定义设置。

protected void Page_Load(object sender, EventArgs e)
{
    using (IDBProvider dbProvider = DBFactory.CreateProvider())
    {
        Response.Write(dbProvider.UploadFile("abc"));
    }
    
    using (IDBProvider dbProvider = DBFactory.CreateProvider("CustomFilePath"))
    {
        Response.Write(dbProvider.UploadFile("xyz"));
    }
}

构建 Web.config 文件

如果您查看配置设置,我们有默认配置“DefaultFilePath”。如果我们不指定自定义文件路径,它将使用默认设置。这种配置设置在测试特定模块时非常有用。由于开发服务器的安全原因,我们无法访问与实际生产服务器类似的功能;在这种情况下,我们可以根据本地机器配置我们的设置,从而帮助我们测试模块并模拟实际环境。

<configSections>
    <section name="dbConfiguration" 
	type="Project.Practice.DB.Configuration.DBSettings,Project.Practice.DB,
    	Version=1.0.0.0, Culture=neutral, 
	PublicKeyToken=e6353c372c56789" allowDefinition="Everywhere" 
    allowExeDefinition="MachineToApplication" restartOnExternalChanges="true"/>
</configSections>
<!-- DB Configuration -->
<dbConfiguration defaultDBProvider="DefaultFilePath">
    <dbProviders>
	<add name="DefaultFilePath" 
	type="Project.Practice.DB.DBProvider,Project.Practice.DB" userID="admin" 
	password="admin" server="militaryZoneArea" database="xyz"/>
	<add name="CustomFilePath" 
	type="Project.Practice.DB.DBProvider,Project.Practice.DB" userID="admin" 
	password="admin" server="militaryZoneArea" database="xyz"/>
    </dbProviders>
</dbConfiguration>

为类库 DLL 生成公钥令牌

可以使用以下步骤为上述配置创建公钥。转到 Visual Studio 命令提示符并运行以下命令:

D:\SampleCustomBlock\bin\Debug>sn -T Project.Practice.DB.dll

Microsoft (R) .NET Framework 强签名工具 版本 2.0.50727.42 版权所有 (C) Microsoft Corporation。保留所有权利。

公钥令牌为 exxx78fd9i34545。确保您已为给定的 DLL 创建了强密钥。如果不需要公钥,则可以指定 public key=null

参考

结论

如果您在运行演示代码时遇到问题,请给我留言。我会尽力帮助您。欢迎对本文提出任何建议或更新。

© . All rights reserved.