- PR -

ASP.NET2.0でカスタムセクションの取得クラスのアセンブリが認識されない

1
投稿者投稿内容
マグノリア
会議室デビュー日: 2005/07/20
投稿数: 7
投稿日時: 2007-12-01 07:02
はじめまして。
現在ASP.NET2.0&C#で開発をしています。

今回 Web.Config でカスタムセクションを定義し、その値の取得用に ConfigurationSection クラスを継承したハンドラクラスを作成して値を参照しようとしているのですが、実行時エラーで、『ファイルまたはアセンブリ 'MyCustomConfigurationHandler, Version=1.0.0.0'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。 』 のExceptionが発生して、その原因がまったく分からない状態です。

どうしても分からず、MSDN の "方法 : ConfigurationSection を使用してカスタム構成セクションを作成する" (http://msdn2.microsoft.com/ja-jp/library/2tw134k3(VS.80).aspx)に記載されているソースをそのまま使って、Web.Config 設定とハンドラクラスを作成したのですが、やはり同様でした。

実はコンパイル時点で既にインフォメーションレベルで Web.Config ファイルに対して "属性 'myCustomSection' のスキーマ情報が見つかりませんでした。" が表示されています。(この時点で既にアセンブリを認識されていない・・)

MSDN と違う点は、
@section の type属性 が Versionまでしか入れていない
 (アセンブリのバージョンは確認済み)
<section
name="myCustomSection"
type="MyConfigSectionHandler.MyHandler, MyCustomConfigurationHandler, Version=1.0.0.0"
allowLocation="true"
allowDefinition="Everywhere"
/>

Aソリューションのフォルダ構成は宇宙仮面さんの
http://uchukamen.com/ASPNET20/ConfigSectionHandler/
に記載されているようになっていて、保存場所は

Root
|- Web (Web.Configを含む WebApplication フォルダ)
| |- bin (Handler Class のアセンブリ参照 DLL)
|
|- MyConfigurationSectionHandler(Handler Class を含む)

のようになっています。

B参照はアセンブリ参照で、MyConfigurationSectionHandler\bin\Debug\***.dllとしています。

アセンブリ参照の仕方、またはソリューションのフォルダ構成に問題があるのではないかと、いろいろ組みなおしたのですがお手上げでした。

どなたか思い当たることがあればご教授お願いいたします。
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2007-12-01 19:01
type属性に指定する値は、型のアセンブリ修飾名です。アセンブリ修飾名の形式は決まっていて、型名、アセンブリ名、バージョン、カルチャ、公開キートークンが必須です。

カルチャは特に指定していないのであればneutral、公開キートークンはアセンブリに署名を行っていないのであればnullでOKです。


Fuga.Piyo, Hoge, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

なお、型のアセンブリ修飾名は、TypeクラスのAssemblyQualifiedNameプロパティで取得できます。

http://msdn2.microsoft.com/ja-jp/library/system.type.assemblyqualifiedname.aspx
_________________
C#と諸々
マグノリア
会議室デビュー日: 2005/07/20
投稿数: 7
投稿日時: 2007-12-02 06:00
よこけんさん。
適切な回答ありがとうございました。

Typeクラスでアセンブリの情報が取得できるとは、勉強不足でした。。
アセンブリの扱いに不慣れでして、参照とか、ディレクトリ構成に原因があるのかと思い、ディレクトリ構成にばかり気を取られていましたが、全て解決しそうです。

MSDNサンプルは私のところでも動いて、あとは今回設定したいカスタムセクションに置き換えて動けば、と考えています。(実装はこれからですが・・)
今回は前アプリケーションからカスタムセクションの設定値をstaticで取得したいと考えています。
マグノリア
会議室デビュー日: 2005/07/20
投稿数: 7
投稿日時: 2007-12-05 22:46
カスタム構成セクションの取得はできたのですが、ハンドラを静的な扱い方がわかりませんでした。。
以前はIConfigurationSectionHandlerインターフェイスを継承したクラスを作成して静的なメンバを持ち、CreateメソッドでXMLnodeでひとつずつ要素直指定することによって静的メンバを初期化することができたのですが、今回は@このCreateメソッドに代わるものが見つからないAConfigurationSectionを継承したクラスの中でConfigurationElementを継承したカスタムハンドラの静的な扱いがわからない・・など、まったく手がかりがない状態です。
カスタム構成セクションの情報は、至るところで頻繁に参照されるものなので、都度ハンドラクラスのインスタンスを作成して参照(つまり都度XMLからセクションを読み込む)するというのはパフォーマンスが落ちる気がしてなりません。
今やろうとしていることは、いくつかに分類された設定値をひとつのハンドラで取得する静的クラスを作成することで、取得したいセクションは以下になります。

<configSections>
<section name="AppConfiguration" type="TESTProject.Web.SystemFramework.AppConfigHandler, SystemFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>

<AppConfiguration>
<TraceValue TraceDir="C:/ProjectName/Log"
         TraceExtend=".log"
         …
         … />
<CustomValue CustomValue1="xxx"
         CustomValue2="yyy"
         …
         … />
<ScreenValue ScreenValue1="zzz"
         …
         … />
</AppConfiguration>

このように分類して記述したセクションの AppConfiguration の子要素である、TraceValue、CustomValue 、ScreenValue のそれぞれについて ConfigurationElement を継承したElementクラスを作成して、それを ConfigurationSection を継承した AppConfigHandler のメンバに追加してアクセスする、というものです。
現在はインスタンスクラスしか動いていないのですが、Elementは以下のようになっています。
public class TracingConfigElement : ConfigurationElement
{
[ConfigurationProperty("TraceDir", DefaultValue = "ap1", IsRequired = true)]
public String TracingTraceDir
{
get
{
return (string)this["TraceDir"];
}
}

[ConfigurationProperty("TraceExtend", DefaultValue = "ap1", IsRequired = true)]
public String TracingTraceExtend
{
get
{
return (string)this["TraceExtend"];
}
}
}

で、このElementをプロパティとして提供するハンドラが以下になります。

public class AppConfigHandler : ConfigurationSection
{
// 子要素
[ConfigurationProperty("TraceSection")]
public TracingConfigElement TraceElement
{
get
{
return (TracingConfigElement)this["TraceSection"];
}

}

// 上記の形で他の子要素についても同様に記述・・
     (略)
}

各ページで以下のように使用する

AppConfigHandler.TraceElement.TracingTraceDir


現在は以下でGetSectionを行うことで使用しています。

AppConfigHandler apconfig = (AppConfigHandler)WebConfigurationManager.GetSection("appConfiguration");


この動きをこの周辺のクラスを使用して静的に実装することは不可能なのでしょうか?


[ メッセージ編集済み 編集者: マグノリア 編集日時 2007-12-05 22:48 ]
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2007-12-06 12:57
> この動きをこの周辺のクラスを使用して静的に実装することは不可能なのでしょうか?

IConfigurationSectionHandler インターフェイスによるカスタムセクション開発を
行ったことがないのでなんとも言えないのですが、少なくとも私は知らないです。

直接的な回答ではありませんが、
コンフィギュレーション周りではなく、それを使用する側に目を向けてみてはどうでしょう。
取得した設定値は、クラスのフィールドとして保持しておいたり、場合によってはシングルトンパターンが役立つかもしれません。

_________________
C#と諸々
マグノリア
会議室デビュー日: 2005/07/20
投稿数: 7
投稿日時: 2007-12-06 22:45
よこけんさん、いつも助言を頂きましてありがとうございます。

今回の製作で構成セクションハンドラは基盤中の基盤となるクラスとなり、今後の自分のためにも、と思ってどうしてもしっかりと作りたかったのですが、やはり状況変わらずでした。
さすがにこれ以上時間がかけられず、ご指摘のシングルトンパターンで行こうと決断しました。

以前記述したカスタムセクションクラスとエレメントクラスを元しています。
カスタムセクションのみ記述すると、

public class AppConfigHandler : ConfigurationSection
{

// セクション定義
private const string TEST_CONFIGURATION = "TESTConfiguration";
private const string TRACING_SECTION = "Tracing";

// AppConfigHanlerのアクセサー
private static AppConfigHandler appConfigHandler;

public static void GetInstance(string AppliationRoot)
{
Type tp = typeof(AppConfigHandler);

lock (tp)
{
if (appConfigHandler == null)
{
// カスタム構成セクションハンドラ作成
appConfigHandler = (AppConfigHandler)WebConfigurationManager.GetSection(TEST_CONFIGURATION);

}
}
}

[ConfigurationProperty(TRACING_SECTION)]
private TracingConfigElement TracingElement
{
get
{
return (TracingConfigElement)this[TRACING_SECTION];
}
}

public static bool TraceEnabled
{
get { return appConfigHandler.TracingElement.TracingEnabled; }
}

public static string TraceDir
{
get { return appConfigHandler.TracingElement.TracingTraceDir; }
}

……
}

となっております。
エレメントクラスの変更点は、以前 public で宣言していたスコープを internal に変更しただけです。
ウェブページのある名前空間とこれらのクラスの名前空間を分けているので、GetInstance 以外は、一応ラップされているかな・・と。

形になったことを感謝します。
ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)