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

发布于 2024-09-30 12:12:43 字数 1166 浏览 1 评论 0原文

为每个 dll 创建设置后,会生成 .dll.config 文件。如果该 dll 是 asp.net 应用程序的一部分,如何为每个 dll 保留此配置,并且不将它们合并到 web.config?

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

GMailSender gms = new GMailSender();
gms.To = "[email protected]";
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 就独立于谁使用他来检索其配置(加载此 DLL 的当前 AppDomain)。

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

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

这是一个基于插件的设计,最终MEF现在在.NET 4.0中做了一些事情,但是Parts 配置也存在同样的问题。有了MEF,至少我不再需要争论基于插件的设计优势。

After creating settings for each dll, a .dll.config file is generated. If that dll be part of an asp.net application, how to keep this configurations separate for each dll and don't merge them into web.config ?

Example:
I have a GMailSender class library (DLL) which sends email via GMail servers. All you need is an instance of GMailSender, like this:

GMailSender gms = new GMailSender();
gms.To = "[email protected]";
gms.Subject = "System.Configuration dilemma";
gms.Body = "Can anyone help me with this question ?";
gms.Send();

Consider GMailSender is inside GMailSender.dll and it's configuration file is GMailSender.dll.config and the username and password of GMail account are inside it.

I want this DLL use the config file of itself (both dll and config in the same directory, i.e in Bin folder of an ASP.NET application) or beside a desktop application. This way the GMailSender is independent of who is using him for retrieving it's configurations (current AppDomain who has loaded this DLL).

I want this without reconstructing the wheel (no custom configuration classes). I guess its possible with System.Configuration but this namespace is probably the worst designed of .NET !

Please don't tell why you designed so that ...

This is a plug-in based design and finally MEF do some kind of it now in .NET 4.0, but there's the same problem for Parts configurations. With MEF at least I don't need anymore to argue for plugin-based design advantages.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

·深蓝 2024-10-07 12:12:43

您可以使用自定义配置部分来实现您的需求。这篇 MSDN 文章提供了有关如何实现此类配置部分的一些详细信息和示例。

如果您需要简单的键/值配置(例如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() 方法或通过实现 从 GmailSettings 访问设置辅助类如下所示:

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"] 一样访问设置。

希望这有帮助。

What you need can be achieved using Custom Configuration Sections. This MSDN article provides some details and samples on how to implement such config sections.

If you need simple key/value configs, like in the appSettings section, then creating a custom configuration section is quite simple.

The first thing you need to do is define your config section inside web.config:

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

Now inside the web.config file you can declare the GmailSettings section and set the location of the external config file that you are going to use for that setting:

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

configSource specifies the name and location of the external config file used for defining the GmailSettings section. Please note the restartOnExternalChanges attribute used when defining the section. Set it to true if you want the application to be automatically restarted when you modify the GmailSettings.config file (as it does when you modify the web.config file).

Below is an example of how to implement the GmailSettings.config file:

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

You can access the settings from GmailSettings using the ConfigurationManager.GetSection() method or by implementing a helper class like the one below:

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]; }
    }
}

The settings can now be accessed like GmailSettings.Instance["userName"].

Hope this helps.

假情假意假温柔 2024-10-07 12:12:43

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

但是,

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

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

一个好的做法是使用配置节,将它们合并到单个配置文件中时很容易维护。

Creating an App.config for a DLL is not a good practice. Configuration belongs to the running application. The class library dll is supposed only to provide services to the calling application.

HOWEVER

If you wrote the DLLs on your own, then you can make these DLL's code prefer their own independent .dll.config file rather than the global App.config/Web.config (in your ASP.NET case) using a trick.

This method allows you to open any executable file's .config file, but no one prevents you from calling it with "Mydll.dll" as argument, and has the same effect. But this works only if you can access these DLL's code.

A good practice is to use configuration sections, which are easy to maintain when merged inside a single configuration file.

素手挽清风 2024-10-07 12:12:43

为了做我相信你想做的事——给你的 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 的新实例并将其返回给调用者。

注释

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

祝你好运!

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

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

To do what I believe you want to do -- give your DLL a configuration file about which referencing assemblies need no nothing, you can[1] do something like the following code.

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 ;
    }

}

This factory method does the following:

  1. Finds the fully-qualified path of the assembly of the caller ((not that of the assembly containing the factory -- it, after all, might be in its own DLL).

  2. Tacks a ".config" on to the end of that path (thus yielding something like 'C:\usr/bin/local/foo/myAssembly.dll.config'.

  3. Ensures that that file exists and is readable, throwing an appropriate exception if not.

  4. Using that path as the source, instantiates a new instance of System.Configuration.Configuration and returns it to the caller.

Notes

  • Visual Studio will take an app.config in your DLL project and turn it into a foo.dll.config file, but your build/deploy/install system is responsible for copying it to the correct location(s). Visual Studio will put it in the bin directory for the DLL project, but it won't get copied any further up the line.
  • You may need to do some experimenting -- you might need to include appropriate entries in the element, even for "standard" sections, since you're outside the normal config file hierarchy. I'm not sure on this, though. In my test, it found and loaded the element without a element defined, so you might have full access to the user and machine config files as well, but I don't make any guarantees about that. YMMV and all that.

Good Luck!

[1] TMTOWTDI as they say in Perl (There's more than one way to do it). You could also, for instance, create a custom section and park it in machine.config.

And there's no requirement that you use the .Net configuration system for this: your factory method could slurp in any arbitrary XML and deserialize it into an object of your choice. This would give you a strongly typed, bound access to the configuration properties, albeit at the expense of automatic refreshing when the config file gets changed. Although...you could also just put a wrapper around the standard Configuration object that would provide the same thing.

东北女汉子 2024-10-07 12:12:43

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

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

我认为这不是过去设计师的本意,而近年来构图开始流行。

What you are looking for cannot be done out of the box. Also, ASP.NET do a shadow copy on DLLs so writing a custom configuration class is not easy to. Your DLLs are not run from Bin folder. THey run from appDomainSetup.CachePath so the *.dll.config files are not beside their assemblies at run-time.

You can add a refrence to *.dll.config files inside web.config instead of copy/paste all key/values from DLL configuration files into web.config; This is possible by using File element in web.config.

I think this is not intended by designers in past and composition became popular in recent years.

未央 2024-10-07 12:12:43

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

ConfigurationManager.AppSettings["DllName.MySetting"]

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

I would add configuration settings to the web.config file and call:

ConfigurationManager.AppSettings["DllName.MySetting"]

This means all configuration settings are in one place and not in the Bin folder.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文