11

最近、IPアドレスを必要とするクラスを含むDLLをC#(.Net 2.0)で作成しました。私の同僚は、「。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フォーラムでこの問題への参照を見つけました:

「古い」値(開発時に定義した値)はハードコーディングされています。franeworkが構成ファイルにアクセスまたは開くことができない場合は、代わりにデフォルトが使用されます。これは、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サービスプロジェクト)の両方で設定する必要があります。

プロジェクトの設定ファイルを作成すると、アプリケーション構成ファイルが追加されるという点で正しいです。設定に入力した値は、構成ファイルと、設定インフラストラクチャによって作成されたクラスの属性の2つの場所に保存されます。構成ファイルが見つからない場合は、属性に埋め込まれている値が使用されます。

このような属性を示すスニペットは次のとおりです。

生成されたクラスの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>

これらのセクションを「true」構成ファイルにコピーする必要があります。

于 2008-10-10T19:55:48.913 に答える
2

私は長い間これと同じ問題を抱えていました-それは迷惑です。

独自の構成ファイルを作成し、各DLLにそれを解析させるというアイデアは気に入っていますが、それでも構成を変更しなければならないことを見逃しがちです。

少なくともこれを少し簡単にするために過去に行ったことの1つは、Setting1.Settingsファイルの構成値が無効であることを確認することです。

たとえば、LINQ-To-SQLを使用してDBと通信するクラスがあります。したがって、データベースへの接続文字列を格納するSetting1.settingsファイルがあります。入力されるデフォルト値(データベーステーブルをデザイナにドラッグアンドドロップしたとき)は、devデータベースの接続文字列です。

テストデータベースに基づいてDBMLファイルを作成したら、設定ファイルにアクセスして編集し、「FAKE_DATABASE」のようなデータベース名を入力できます。

そうすれば、別のプロジェクトでDLLを使用し、構成ファイルをマージしてDLLの適切な構成値を追加するのを忘れた場合、少なくとも「FAKE_DATABASEに接続できません」などのエラーが発生します。

もちろん、デザイナーと再度作業する必要がある場合は、値を開発データベースの値に戻す必要があります。

大きな痛み。彼らはどうにかしてこれを変えなければならない。

于 2008-11-12T16:52:03.237 に答える
2

私はプロトタイピングの最中にあるアプリケーションでこの正確な問題に取り組んでいます。構成ファイルをまとめてハッキングするという Decker の提案は機能するはずですが、これはビルド サイクルの一部として手動でハックするのはかなり不便だと思います。その代わりに、最もクリーンな解決策は、各ライブラリに独自の library.dll.config ファイルを解析させることだと判断しました。まだ完全ではなく、追加の定型コードが必要ですが、.Net がこれらの app.config ファイルを処理する複雑な方法を回避する唯一の方法のようです。

于 2008-10-10T20:18:43.437 に答える
1

DLLとテストアプリケーションでこれが機能しない理由の説明を見つけたと思います。これが誰かのブログからの最後の例外です:

これに対する修正は、アプリケーションとサポートアセンブリが同じ名前空間を持っていることを確認するか、AppName.exe.configとDllName.dll.configの内容をマージすることを確認することです(はい、.dllをコンパイルすると生成されます)このファイル。ただし、アプリケーションディレクトリにコピーすると無視され、自動的にマージされません)

したがって、DLLとアプリケーションを同じ名前空間に保持する必要があります。または、DLL構成ファイルの内容をアプリケーションの構成ファイルとマージする必要があります。

(この種のDLLの目的は損なわれませんか?DLLは独立したライブラリであると考えられていました。)

おそらくこれが私の同僚のために働く理由です。本番アプリケーションは、DLLと同じ名前空間を共有します。(私のテストアプリは明らかにそうではありません...)

更新: 最近同僚と座ってこの問題についてもう一度話しましたが、彼にとってもうまくいかなかったようですが、初期値をと同じに設定していたため、彼は気づいていませんでした。私たちが使おうとしていたデバイス。もちろん、最初は機能しているように見えましたが、設定が少し異なる他の場所に展開するとすぐに、再び壊れました。

于 2008-10-10T21:17:04.177 に答える
1

どうやらあなたのアプリケーションはデフォルトの設定ファイル(おそらくアプリケーションの設定ファイル)から読み込もうとしています。確認するには、dllの構成ファイルのキーと値のペアをアプリケーションの構成ファイルに追加し、アプリケーションを実行して、今回読み取られるかどうかを確認します。

于 2008-10-10T19:04:37.177 に答える
0

app.configを使用すると、同様の問題が発生します。Visual Studioからではなく.exeからアプリケーションを実行してみて、期待どおりに動作するかどうかを確認してください。

于 2008-10-10T19:52:33.833 に答える
-1

皆さんが犯していると思う間違いは、Settings1.Default.IPAddress単にこれを行うことが想定されているのに、どうやら DLL の設定を参照しているようだということSettings1.IPAddressです。

違いはSettings1.Default.IPAddress、値を使用すると、アセンブリ ファイル (.dll または .exe) に属性 [global::System.Configuration.DefaultSettingValueAttribute(...)] として埋め込まれたハードコードされた値から取得されることです。

WhileSettings1.IPAddressは、ファイル.dll.config(XML ファイル) で編集可能な値です**。そのため、XML ファイルに加えた変更は、アセンブリ内のハードコードされた既定値には反映されません。

これではない:

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

しかし、これを試してください:

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