如果ASP.NET应用程序使用许多DLL,那么保持每个dll的配置分离的最佳方法是什么?

时间:2010-10-31 20:54:01

标签: asp.net configuration web-config

为每个dll创建设置后,会生成一个.dll.config文件。如果dll成为asp.net应用程序的一部分,那么如何为每个dll分隔这些配置并且不将它们合并到web.config中?

实施例: 我有一个GMailSender类库(DLL),它通过GMail服务器发送电子邮件。您只需要一个GMailSender实例,如下所示:

GMailSender gms = new GMailSender();
gms.To = "myfriend@yahoo.com";
gms.Subject = "System.Configuration dilemma";
gms.Body = "Can anyone help me with this question ?";
gms.Send();

考虑GMailSender位于GMailSender.dll内,其配置文件为GMailSender.dll.config,其中包含GMail帐户的用户名和密码。

我希望这个DLL使用自身的配置文件(同一目录中的dll和config,即ASP.NET应用程序的Bin文件夹中)或桌面应用程序旁边。通过这种方式,GMailSender独立于谁使用他来检索它的配置(当前AppDomain已加载此DLL)。

我想要这个而不重建轮子(没有自定义配置类)。我想它可能与System.Configuration,但这个命名空间可能是最糟糕的.NET设计!

请不要告诉你为什么设计这样......

这是基于plug-in的设计,最后MEF现在在.NET 4.0中执行某种操作,但Parts配置存在同样的问题。至少MEF我不再需要争论plugin-based设计优势了。

5 个答案:

答案 0 :(得分:4)

使用自定义配置栏可以实现您的需求。这个MSDN article提供了有关如何实现此类配置部分的一些细节和示例。

如果您需要简单的键/值配置,例如在appSettings部分,那么创建自定义配置部分非常简单。

您需要做的第一件事是在web.config中定义配置部分

<configSections>
  <section name="GmailSettings" restartOnExternalChanges="true" type="System.Configuration.NameValueFileSectionHandler" />
</configSections>

现在,在web.config文件中,您可以声明 GmailSettings部分,并设置您将用于该设置的外部配置文件的位置:

<GmailSettings configSource="GmailSettings.config"></GmailSettings>

configSource 指定用于定义GmailSettings部分的外部配置文件的名称和位置。请注意定义部分时使用的restartOnExternalChanges属性。如果您希望在修改GmailSettings.config文件时自动重新启动应用程序(就像修改web.config文件时那样),请将其设置为true。

以下是如何实施 GmailSettings.config 文件的示例:

<?xml version="1.0"?>
<GmailSettings>
  <add key="userName" value="blabla"/>
  <add key="password" value="moreBla"/>
</GmailSettings>

您可以使用ConfigurationManager.GetSection()方法或通过实施帮助类来访问Gmail设置中的设置,如下所示:

public class GmailSettings
{
    private static readonly GmailSettings _instance = new GmailSettings();
    private NameValueCollection _settings = ConfigurationManager.GetSection("GmailSettings") as NameValueCollection;

    public static GmailSettings Instance
    {
        get { return _instance; }
    }

    public string this[string key]
    {
        get { return _settings[key]; }
    }
}

现在可以像GmailSettings.Instance["userName"]一样访问设置。

希望这有帮助。

答案 1 :(得分:1)

为DLL创建App.config不是一个好习惯。配置属于正在运行的应用程序。类库dll应该只为调用应用程序提供服务。

无论其

如果您自己编写DLL,那么您可以使这些DLL的代码更喜欢他们自己的独立.dll.config文件而不是全局App.config / Web.config(在您的ASP.NET情况下)使用技巧

This method允许您打开任何可执行文件的.config文件,但是没有人阻止您使用“Mydll.dll”作为参数调用它,并且具有相同的效果。但这只有在您可以访问这些DLL的代码时才有效。

一个好的做法是使用配置部分,这些部分在单个配置文件中合并时易于维护。

答案 2 :(得分:1)

要做我认为你想做的事情 - 给你的DLL一个配置文件,关于哪些引用程序集不需要任何东西,你可以[1]做类似下面的代码。

static class DllConfigurationFactory
{
    public static Configuration GetConfigurationInstance()
    {
        string           callingAssemblyPath = Assembly.GetCallingAssembly().Location ;
        string           configFilePath      = string.Concat( callingAssemblyPath , ".config" ) ;

        // getAttributes hurls with a multitude of exceptions
        FileAttributes   attributes  = File.GetAttributes( configFilePath ) ;
        bool             isDirectory = ( (attributes&FileAttributes.Directory) == FileAttributes.Directory ? true : false ) ;
        if ( isDirectory )
        {
            throw new FileNotFoundException() ;
        }

        // check for (and die with an SecurityException) if we dont' have read access
        new FileIOPermission( FileIOPermissionAccess.Read , configFilePath ).Demand() ;

        ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
        configMap.ExeConfigFilename = configFilePath ;
        Configuration instance = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
        return instance ;
    }

}

此工厂方法执行以下操作:

  1. 查找调用者程序集的完全限定路径(不是包含工厂的程序集的路径 - 毕竟,它可能位于自己的DLL中)。

  2. 在该路径的末尾添加“.config”(从而产生类似'C:\ usr / bin / local / foo / myAssembly.dll.config'的内容。

  3. 确保该文件存在且可读,如果没有,则抛出适当的异常。

  4. 使用该路径作为源,实例化System.Configuration.Configuration的新实例并将其返回给调用者。

  5. 备注

    • Visual Studio将在您的DLL项目中使用app.config并将其转换为foo.dll.config文件,您的构建/部署/安装系统负责将其复制到正确的位置位置(一个或多个)。 Visual Studio会将它放在DLL项目的bin目录中,但它不会被复制到任何进一步的行。
    • 您可能需要进行一些实验 - 您可能需要在元素中包含适当的条目,即使对于“标准”部分也是如此,因为您不在正常的配置文件层次结构中。不过,我不确定。在我的测试中,它发现并加载了没有定义元素的元素,因此您也可以完全访问用户和机器配置文件,但我不保证这一点。 YMMV等等。

    祝你好运!

    [1] TMTOWTDI正如他们在Perl中所说的那样(有多种方法可以做到这一点)。例如,您还可以创建一个自定义部分并将其停放在machine.config中。

    并且没有要求您使用.Net配置系统:您的工厂方法可能会插入任意XML并将其反序列化为您选择的对象。这将为您提供对配置属性的强类型绑定访问,尽管以配置文件更改时自动刷新为代价。虽然......你也可以在标准的Configuration对象周围放一个包装器来提供相同的东西。

答案 3 :(得分:1)

您正在寻找的东西无法开箱即用。此外,ASP.NET在DLL上执行卷影复制,因此编写自定义配置类并不容易。您的DLL不从Bin文件夹运行。从appDomainSetup.CachePath运行,因此* .dll.config文件在运行时不在其程序集旁边。

您可以在web.config中添加对.dll.config文件的引用,而不是将DLL配置文件中的所有键/值复制/粘贴到web.config中;这可以通过在web.config中使用File元素来实现。

我认为这不是过去设计师的意图,近年来作品变得流行。

答案 4 :(得分:0)

我会将配置设置添加到web.config文件并调用:

ConfigurationManager.AppSettings [ “DllName.MySetting”]

这意味着所有配置设置都在一个位置,而不是在Bin文件夹中。