トップ回答者
ライブラリプロジェクト内の相対パス

質問
-
ASP.net Framework3.5 C# で開発しております。(IIS Express)
ソリューション構成として
ASP プロジェクトの他に、クラスライブラリがあります。
+ ASP
+ クラスライブラリ
また、このクラスライブラリプロジェクトは
+ Aフォルダ
- A.cs
+ Bフォルダ
- B.xml
のような構成になっております。
課題としては、
上記A.cs内でB.xmlのパス指定をしたいのですが、CurrentFolderがIISフォルダになってしまい、
パスの指定方法が分かっておりません。
どのように指定すればよろしいのでしょうか?
- 編集済み rakman 2015年4月10日 7:40
回答
-
【追伸】
先のレスで、
> xml ファイルは未検証ですが
と書きましたが、できないと何なので一応検証してみました。
ASP.NET Web アプリと同じソリューション内に別のプロジェクトとして ClassLibrary1 という名前のプロジェクトを作成。その直下にクラスライブラリ (A.cs) と .xml ファイル (B.xml) の両方を配置(フォルダを分けると名前空間の扱いが面倒なので)という形です。
.xml ファイルと .aspx ファイルは以下のチュートリアルからそのまま借用。
チュートリアル : ASP.NET トレースと System.Diagnostics トレースの統合
https://msdn.microsoft.com/ja-jp/library/b0ectfxd(v=vs.100).aspxクラスライブラリ(上のチュートリアルで言うと AuthorClass ビジネスオブジェクト)は埋め込みリソースを読むように修正して以下の通りです。ブラウザから URL 参照して取得するわけではないので、先に紹介した記事「リソース埋め込みカスタムコントロール」に書いてあるような WebResource 関係の設定は不要です。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Configuration; using System.Configuration; using System.Collections; using System.Data; namespace ClassLibrary1 { public class AuthorClass { private DataSet dsAuthors = new DataSet("ds1"); private System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly(); public AuthorClass() { System.IO.StreamReader sr = new System.IO.StreamReader( myAssembly.GetManifestResourceStream("ClassLibrary1.Authors.xml"), System.Text.Encoding.UTF8); dsAuthors.ReadXml(sr, XmlReadMode.ReadSchema); } public DataSet GetAuthors() { return dsAuthors; } } }
- 回答としてマーク rakman 2015年4月16日 7:20
-
埋め込む方法を把握できていないのに、読み出し方だけを質問しても答えが得られるわけがありません。
コンパイル時に埋め込む方法ですが、プロジェクトにリソースファイル(拡張子.resx)を追加してください。リソースファイルには文字列以外にもファイルをリソースとして埋め込む機能が提供されています。
こうすると自動的に.Designer.csが生成され、各リソースにアクセスできるプロパティが用意されます。実行時にはそのプロパティを読み込むことでアクセスできます。
リソースの追加と編集が参考になります。SurferOnWwwさんの提示されている方法も内部的には同様の処理をしていますが、リソースファイルを用いた方が管理が楽になります。
すべての返信
-
回答ではなく、質問ですみません。
> ASP プロジェクトの他に、クラスライブラリがあります。
先の質問者さんのスレッドの話から続いているとすると、その ASP というのは、ASP.NET Web Forms アプリですよね?(クラシック ASP ではなくて・・・用語はきちんと使わないと掲示板では話が通じにくくなりますのでご注意ください)。
A.cs というのがどういうクラスライブラリなのか分かりませんが、何にせよそれは ASP.NET Web アプリが使うクラスライブラリですよね。
そして、B.xml というのは ASP.NET Web アプリがデータソースとして使うのですよね(B.xml を読んだり更新したりするのは A.cs の中のコードだとしても)。
そうであれば、データソースは ASP.NET Web Forms アプリのルート直下の App_Data フォルダに入れるのが普通だと思います。
そのようにはできないのでしょうか?
今の質問者さんの案で考えて回答しても、最終的には App_Data に置くという話になると二度手間ですのでお聞きしています。
【追記】
B.xml を App_Data フォルダに置けば、A.cs のコードでは以下のように物理パスを取得できます。
string filePath = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/B.xml");
- 編集済み SurferOnWww 2015年4月10日 8:34 追記追加
-
ありがとうございます。
はい、ASPのプロジェクトはASP.NET Web アプリケーションです。
クラスライブラリはプロジェクトプロパティのプロジェクト依存関係で設定しているライブラリを指しております。
現状、B.xmlをApp_Dataフォルダに配置することも可能なのですが、このクラスライブラリを将来的に今は必要でない
別プロジェクトからも参照できるような形にできればと思いまして、ライブラリ内に配置できればと考えました。
(また、クラスライブラリはソリューションビルド時にdllになりますのが、xmlもバイナリ化されるものなのでしょうか?)
背景が説明不足ですみません。
App_Dataフォルダに配置した場合、提示して頂いた内容で取得できました。
-
A.cs と B.xml の ASP.NET Web アプリにおける位置づけは何なのですか? それを明確にしてくれないと話が通じないですよ。
以下のどちらかだと想像してますが、どちらなのでしょう? (どちらにも該当しない場合は、質問者さんが考えている関係を詳しく書いてください)
(1) 三層構造、すなわち、プレゼンテーション層 / ビジネス層 / データー層を考えていて、ASP.NET Web アプリ(プレゼンテーション層)が A.cs(ビジネス層)経由で B.xml(データ層)を読んだり更新したりする。
(2) カスタムコントロールとそれ専用の埋め込み画像やスクリプトのような関係(前者が A.cs、後者が B.xml)で、ASP.NET Web アプリからは A.cs しか見えない。B.xml を更新するようなこともない。
もし、(1) であれば、先の私のレスで書いたとおり B.xml は ASP.NET Web アプリのルート直下の App_Data フォルダに置く以外の選択肢ないと思います
もし、(2) であれば、B.xml をリソースとして埋め込むことができると思います。カスタムコントロールの例ですが、以下の記事が参考になりませんか。(xml ファイルは未検証ですが)
リソース埋め込みカスタムコントロール
http://surferonwww.info/BlogEngine/post/2012/05/19/Web-custom-control-with-embedded-resources.aspx -
もし、(1) であれば、先の私のレスで書いたとおり B.xml は ASP.NET Web アプリのルート直下の App_Data フォルダに置く以外の選択肢ないと思います
ちょっと補足情報です。
(1)の場合のフォルダパス取得の方法として、やや裏技ですが、
string folder = (string)AppDomain.CurrentDomain.GetData("DataDirectory");
という方法があります。
この方法だと、ASP.NETでは上記App_Data、通常のWindowsアプリではexeと同じ場所、ClickOnceアプリではデータディレクトリというように、自動でパスを取得できますので、アプリのタイプによって取得方法を変える必要がなくなります。(System.Webの参照設定なども不要)
-
【追伸】
先のレスで、
> xml ファイルは未検証ですが
と書きましたが、できないと何なので一応検証してみました。
ASP.NET Web アプリと同じソリューション内に別のプロジェクトとして ClassLibrary1 という名前のプロジェクトを作成。その直下にクラスライブラリ (A.cs) と .xml ファイル (B.xml) の両方を配置(フォルダを分けると名前空間の扱いが面倒なので)という形です。
.xml ファイルと .aspx ファイルは以下のチュートリアルからそのまま借用。
チュートリアル : ASP.NET トレースと System.Diagnostics トレースの統合
https://msdn.microsoft.com/ja-jp/library/b0ectfxd(v=vs.100).aspxクラスライブラリ(上のチュートリアルで言うと AuthorClass ビジネスオブジェクト)は埋め込みリソースを読むように修正して以下の通りです。ブラウザから URL 参照して取得するわけではないので、先に紹介した記事「リソース埋め込みカスタムコントロール」に書いてあるような WebResource 関係の設定は不要です。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Configuration; using System.Configuration; using System.Collections; using System.Data; namespace ClassLibrary1 { public class AuthorClass { private DataSet dsAuthors = new DataSet("ds1"); private System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly(); public AuthorClass() { System.IO.StreamReader sr = new System.IO.StreamReader( myAssembly.GetManifestResourceStream("ClassLibrary1.Authors.xml"), System.Text.Encoding.UTF8); dsAuthors.ReadXml(sr, XmlReadMode.ReadSchema); } public DataSet GetAuthors() { return dsAuthors; } } }
- 回答としてマーク rakman 2015年4月16日 7:20
-
話が噛み合ってないようです。
> ご提示して頂いた形ですと、(1)になります。
と、
> 求める形としてはDLL内にXMLファイルを埋め込む方法です。
は矛盾していませんか?
先の私のレスの (1) は「 三層構造、すなわち、プレゼンテーション層 / ビジネス層 / データー層を考えていて、ASP.NET Web アプリ(プレゼンテーション層)が A.cs(ビジネス層)経由で B.xml(データ層)を読んだり更新したりする。」です。
「DLL内にXMLファイルを埋め込む」というのは、(1) ではなくて (2) ではないですか?
> そうすると、クラスライブラリ内に配置するのは難しいということですね。やりたいことが (2) でよければ、その具体的な方法を上の私のレスに書きましたが、読んでいただけたでしょうか? それもやりたいことと違う場合は、具体的にどこが違うか書いてください。
-
B.xmlが具体的にどういう内容で、クラスライブラリからどう利用するのか、どういう目的で利用するのかまず明確にする方がいいと思いますよ。
たとえば、ライブラリの動作設定とかに近い内容なら、(1)でも(2)でもなくて、設定情報の扱いで、構成ファイルから読み込む方が適切でしょうし、もしどうしてもB.xmlにしなければならない理由があるなら、設定を変更する可能性があるなら(1)になりますし、あくまでdll埋め込みで変更は必要ない、単なるDLLが動作するための固定データであれば(2)になるでしょうし。
どういう内容のデータで、どういう目的で使うのか、ちょっと明確にしてみましょう。
-
埋め込む方法を把握できていないのに、読み出し方だけを質問しても答えが得られるわけがありません。
コンパイル時に埋め込む方法ですが、プロジェクトにリソースファイル(拡張子.resx)を追加してください。リソースファイルには文字列以外にもファイルをリソースとして埋め込む機能が提供されています。
こうすると自動的に.Designer.csが生成され、各リソースにアクセスできるプロパティが用意されます。実行時にはそのプロパティを読み込むことでアクセスできます。
リソースの追加と編集が参考になります。SurferOnWwwさんの提示されている方法も内部的には同様の処理をしていますが、リソースファイルを用いた方が管理が楽になります。
-
B.xmlはマスタ(表示データを保持)の位置付けで内容変更は不要で、A.csから参照だけされるファイルです。
>カスタムコントロールとそれ専用の埋め込み画像やスクリプトのような関係
こちらの意味が分からず、
実際のフローとしては、Web アプリ開始トリガ → 表示用データ作成(ライブラリA.cs内メソッド呼び出し) →
ライブラリA.cs内メソッド → (表示データを取得する為に)マスタデータ読込(B.xml)という流れですので、
(1) だと考えました。
↓のなちゃさんの説明を元に考えると、(1)と記載したことは間違いでして、(2)が正だと改めました。
皆様、ありがとうございます。
-
ご提示くださった内容でファイルアクセスできました。
ありがとうございます。
すみません、本スレッドとは直接関係ないのですが上記と同じ構造に対してなので、
1つ質問させてください。
Web アプリ開始トリガ(Z.aspx.cs) → 表示用データ作成(ライブラリA.cs内メソッド呼び出し) →
ライブラリA.cs内メソッド
↑この流れの中で、
A.cs内メソッドで、Web アプリ(Z.aspx.cs)で呼び出し可能なメソッド(例.GetLocalResourceObject())を
実行し、Z.aspx.csで呼び出した時と結果を取得することは可能でしょうか?(概要を下記に書きました。)
既存フローに修正を加えている関係で、そもそもの構造に問題があるかもしれませんが、A.csで実行したいメソッドが
ありますので、質問しました。閲覧上、不適切でしたら、一旦この質問を取り消すことに致します。
・Z.aspx.cs
A xClass = new A();
Sample Z = xClass.hoge();
・A.cs (ライブラリ:Class A)
Sample hoge()
{
x = GetLocalResourceObject(・・・); // ←呼び出し元Z.aspx.csでこのメソッドを実行した時と同じ結果を取得したい。現在はエラーで呼び出せません。
return ・・・;
}
-
質問内容が別ならスレッドを分けた方がいいかも知れませんが…
まず、基本として、ライブラリは完全にWebアプリ専用で、Webの仕組みに依存するものだ、という前提でいいんですよね?
※汎用的なライブラリだとこういうのがネックになったりします。
あくまでWeb専用のライブラリというかdllであるという前提として。
Web関連の情報へのアクセスは、基本的にHttpContextというオブジェクトを通じて提供されます。
System.Web.HttpContext.Currentで現在処理中のリクエストに紐づく情報が取得できますので、ここからいろんな機能にアクセス可能です。
ただし、HttpContexは完全にWebアプリのリクエストの処理スレッドに依存しますので、たとえばスレッドを別に作成したりスレッドプールで実行するような処理では使えない、Webリクエスト以外の処理でももちろん使えない、などの制限があります。
また、リクエスト依存の処理であればたいていHttpContextから直に扱えますが、個別ページなどに依存する処理だと、ページのURLの取得が必要だったりなど、こまごまと工夫などが必要になります。
たとえばGetLocalResourceObjectだと、対象のページの仮想パスが必要になります(現在のリクエストのURLや、ハンドラの情報などから取得はできますが)。
- 編集済み なちゃ 2015年4月16日 6:42
-
> 閲覧上、不適切でしたら、一旦この質問を取り消すことに致します。
不適切とは言えないまでも、好ましいことではないです。表題や最初の質問と質問内容が変わってきた場合は、新に別のスレッドを立てて質問していただくようお願いします。
このフォーラムは開発者同士の情報交換の場所ということを考えていただけれると、そうすることが適切であることは理解いただけると思います。(例えば、検索などでここにたどり着いた人のことを考えてください)
このスレッドの質問の回答は得られたようですので、質問者さんの役に立った回答にチェックマークをつけて(複数可)クローズしてください。