11

我最近用 C# (.Net 2.0) 编写了一个 DLL,其中包含一个需要 IP 地址的类。我的一位同事更改了类以从“.dll.config”(XML)文件中检索 IP——这显然是由他创建的“应用程序设置”文件(Settings1.settings)自动生成的。这样做的好处是允许最终用户随意更改 XML/config 文件中的 IP 地址。

不幸的是,当我从树中检查他的代码并尝试编译(或使用)这个新代码时,任何调用这个 DLL 的应用程序都只会得到默认值,而不是文件中的值。

调用配置文件的构造函数如下所示:

    public class form : System.Windows.Forms.Form
    {
        public form()
        {
            // This call is required by the Windows Form Designer.
            InitializeComponent();
            IP = IPAddress.Parse(Settings1.Default.IPAddress);
        }
    }

在 MSDN 论坛上找到了对此问题的参考,其中一位用户说:

“旧”值(您在开发时定义的值)是硬编码的。如果框架无法访问或打开配置文件,它将使用默认值。如果您在 dll 中使用设置,这种情况总是会发生。

  1. 这是否意味着我不能在配置文件中存储 DLL 的外部值?(我的同事以某种方式完成了这项工作......)

  2. 由于我的框架似乎无法访问或打开配置文件,我该如何找出它失败的原因?甚至检测何时发生这种情况?

德克尔:这有点帮助。不幸的是,我正在将此 DLL 写入规范,因此我实际上无法访问应用程序的配置文件。正如您将在上面提到的,我的同事创建了一个“设置1 .settings”文件。当时我不明白这一点,但现在看来,添加“1”会将其排除在任何调用它的应用程序的设置空间之外。

我想我想弄清楚为什么 DLL 似乎没有在同一目录中找到它旁边的配置文件。一步一步地跟踪代码没有发现任何问题。

顺便说一句,我可以将程序集的“输出类型”从“类库”更改为“Windows 应用程序”,并在 DLL 代码的开头添加以下行:

    [STAThread]
    public static void Main(string[] args)
    {
        System.Windows.Forms.Application.Run(new form());
    }

当我运行它时,它会生成一个不同的配置文件(“.exe.config”),我可以更改该文件并让它从文件中提取新数据。所以我有点困惑。有任何想法吗?

4

9 回答 9

7

我一直使用这种技术。通常我有一个需要某些设置的库程序集,我需要通过测试项目以及主要的“可执行”程序集来设置它们——无论是 Web 项目还是 Windows 服务项目。

您是正确的,当您为任何项目创建设置文件时,它会添加一个应用程序配置文件。您为任何设置输入的值存储在两个位置——配置文件和设置基础结构创建的类的属性中。当未找到配置文件时,将使用嵌入在属性中的值。

这是显示此类属性的片段:

这是一个片段,显示了生成的类中 ConcordanceServicesEndpointName 的默认值:

    [global::System.Configuration.ApplicationScopedSettingAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Configuration.DefaultSettingValueAttribute("InternalTCP")]

    public string ConcordanceServicesEndpointName {
        get {
            return ((string)(this["ConcordanceServicesEndpointName"]));
        }
    }

您要做的是将配置部分从库程序集项目中的 app.config 文件中复制出来,并将其(小心地)合并到主程序集的适用 web.config 或 app.config 中。在运行时,这是唯一使用的配置文件。

这是一个例子:

<configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
      <section name="LitigationPortal.Documents.BLL.DocumentsBLLSettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <applicationSettings>
    <LitigationPortal.Documents.BLL.DocumentsBLLSettings>
      <setting name="ConcordanceServicesEndpointName" serializeAs="String">
        <value>InternalTCP</value>
      </setting>
    </KayeScholer.LitigationPortal.Documents.BLL.DocumentsBLLSettings>
  </applicationSettings>

您应该将这些部分复制到“真实”配置文件中。

于 2008-10-10T19:55:48.913 回答
2

我正在原型设计中的应用程序中解决这个确切的问题。尽管 Decker 建议将配置文件一起破解应该可行,但我认为这是一个非常不方便的手动破解,作为构建周期的一部分执行。而不是我决定最干净的解决方案是让每个库解析自己的 library.dll.config 文件。它仍然不完美,它需要一些额外的样板代码,但它似乎是绕过 .Net 处理这些 app.config 文件的拜占庭方式的唯一方法。

于 2008-10-10T20:18:43.437 回答
2

我有同样的问题很长一段时间 - 这很烦人。

我喜欢制作自己的配置文件并让每个 DLL 解析它的想法,尽管仍然可能很容易错过不得不更改配置的情况。

我过去做过的至少让这更容易的一件事是确保 Setting1.Settings 文件的任何配置值都无效。

例如,我有一个使用 LINQ-To-SQL 与 DB 对话的类。所以它有一个 Setting1.settings 文件,它将连接到数据库的字符串存储在其中。输入的默认值(在将数据库表拖放到设计器中时)是开发数据库的连接字符串。

一旦我基于测试数据库创建了 DBML 文件,我可以进入并编辑设置文件并输入数据库名称,如“FAKE_DATABASE”。

这样,如果您在另一个项目中使用 DLL,然后忘记合并配置文件以添加正确的 DLL 配置值,至少您会收到类似“无法连接到 FAKE_DATABASE”的错误消息。

当然,如果您必须再次与设计器合作,则必须将值更改回您的开发数据库的值。

巨大的痛苦。他们必须以某种方式改变这一点。

于 2008-11-12T16:52:03.237 回答
1

显然您的应用程序正在尝试从默认配置文件(可能是应用程序的配置文件)中读取。为确保,将dll的配置文件中的键值对添加到应用程序的配置文件中,运行应用程序,看看这次是否被读取。

于 2008-10-10T19:04:37.177 回答
1

我想我刚刚找到了为什么这对我的 DLL 和我的测试应用程序不起作用的解释。这是某人博客的结论性例外:

解决此问题的方法是确保您的应用程序和支持程序集具有相同的命名空间,或者确保合并 AppName.exe.config 和 DllName.dll.config 的内容(是的,当您编译 .dll 时,它现在会生成此文件,但是如果您将其复制到应用程序目录并且不会自动合并,则会忽略它)

所以要么我必须将 DLL 和应用程序保持在同一个命名空间中 - 要么 - 我必须将 DLL 配置文件的内容与应用程序的配置文件合并。

(这不是违背了 DLL 的目的吗?我认为 DLL 应该是一个独立的库。)

也许这就是为什么它对我的同事有用。生产应用程序与 DLL 共享相同的命名空间。(我的测试应用程序显然没有......)

更新: 我最近刚和我的同事坐下来再次谈论这个问题,似乎它也从未对他有用,但他没有意识到这一点,因为他将初始值设置为与我们试图使用的设备。所以当然它一开始似乎可以工作,但是一旦我们将它部署到其他设置略有不同的地方,它就又被破坏了。

于 2008-10-10T21:17:04.177 回答
0

我在使用 app.config 时遇到过类似的问题。尝试从 .exe 而不是从 Visual Studio 运行您的应用程序,然后查看它是否按预期运行。

于 2008-10-10T19:52:33.833 回答
0

在您的 DLL 中,您可能将访问修饰符(对于 Settings1.Settings)设置为 Internal(对于 VB 来说是Friend)。尝试将 Access MOdifier 更改为 Public 并查看是否允许您的应用程序从 dll 的配置中读取/写入值。

于 2009-01-06T17:16:25.620 回答
0

霍华德的回答涵盖了理论。

解决此问题的一种快速而肮脏的方法是手动解析 xml 配置文件。

    string configFile = Assembly.GetExecutingAssembly().Location + ".config";
    XDocument.Load(configFile).Root.Element("appSettings")....
于 2017-03-10T10:06:40.680 回答
-1

Settings1.Default.IPAddress我认为你们都犯的错误是,当您只是应该这样做时,您显然是通过引用 DLL 设置Settings1.IPAddress

不同之处在于,当您使用Settings1.Default.IPAddress这些值时,这些值是从作为属性 [global::System.Configuration.DefaultSettingValueAttribute(...)] 嵌入到程序集文件(.dll 或 .exe)中的硬编码值中获取的。

WhileSettings1.IPAddress是文件.dll.config(XML 文件)中可编辑的值**。因此,您对 XML 文件所做的任何更改都不会反映在程序集中的硬编码默认值中。

不是这个:

IP = IPAddress.Parse(Settings1.Default.IPAddress);

但是试试这个:

*IP = IPAddress.Parse(Settings1.IPAddress);
于 2012-08-16T16:00:45.927 回答