質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

5回答

4168閲覧

Visual C#で同一ソリューション内の複数のプロジェクトから共通のクラスを参照するには

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2021/08/29 08:10

現在、以下の様なソリューションを作成しています。
イメージ説明
SubClassX.csの中でFormA,FormBのインスタンスを生成したいのですが、TestAppAではTestAppBの、TestAppBではTestAppAのusingがエラーになります。

C#

1using TestAppA; 2using TestAppB; 3 4namespace TestAppCommon 5{ 6 class SubClassX 7 { 8 FormA classA = new FormA(); 9 FormB classB = new FormB(); 10 11 SubClassA1 class1A = new SubClassA1(); 12 SubClassB1 class1B = new SubClassB1(); 13 } 14}

エラーメッセージは以下になります。

リビルドを開始しました...
1>------ すべてのリビルド開始: プロジェクト:TestAppA, 構成: Debug Any CPU ------
2>------ すべてのリビルド開始: プロジェクト:TestAppB, 構成: Debug Any CPU ------
C:\Users\Owner\source\repos\TestApp\TestAppB\TestAppB.csproj を復元しました (2 ms)。
C:\Users\Owner\source\repos\TestApp\TestAppA\TestAppA.csproj を復元しました (2 ms)。
1>C:\Users\Owner\source\repos\TestApp\TestCommon\SubClassX.cs(2,7,2,15): error CS0246: 型または名前空間の名前 'TestAppB' が見つかりませんでした (using ディレクティブまたはアセンブリ参照が指定されていることを確認してください)
1>C:\Users\Owner\source\repos\TestApp\TestCommon\SubClassX.cs(9,9,9,14): error CS0246: 型または名前空間の名前 'FormB' が見つかりませんでした (using ディレクティブまたはアセンブリ参照が指定されていることを確認してください)
1>C:\Users\Owner\source\repos\TestApp\TestCommon\SubClassX.cs(12,9,12,19): error CS0246: 型または名前空間の名前 'SubClassB1' が見つかりませんでした (using ディレクティブまたはアセンブリ参照が指定されていることを確認してください)
1>プロジェクト "TestAppA.csproj" のビルドが終了しました -- 失敗。
2>C:\Users\Owner\source\repos\TestApp\TestCommon\SubClassX.cs(1,7,1,15): error CS0246: 型または名前空間の名前 'TestAppA' が見つかりませんでした (using ディレクティブまたはアセンブリ参照が指定されていることを確認してください)
2>C:\Users\Owner\source\repos\TestApp\TestCommon\SubClassX.cs(8,9,8,14): error CS0246: 型または名前空間の名前 'FormA' が見つかりませんでした (using ディレクティブまたはアセンブリ参照が指定されていることを確認してください)
2>C:\Users\Owner\source\repos\TestApp\TestCommon\SubClassX.cs(11,9,11,19): error CS0246: 型または名前空間の名前 'SubClassA1' が見つかりませんでした (using ディレクティブまたはアセンブリ参照が指定されていることを確認してください)
2>プロジェクト "TestAppB.csproj" のビルドが終了しました -- 失敗。
========== すべてリビルド: 0 正常終了、2 失敗、0 スキップ ==========

元々TestAppAだけ作成していたのですが、機能分割によりTestAppBを作成することになり、以下の方法で行いました。
(1) TestAppAをインポートして作成したテンプレートでTestAppBを作成。
(2) 双方で共通のクラスSubClassXを新たに作成したTestAppCommonフォルダに移動。
(3) SubClassXのnamespaceをTestAppCommonに変更。
(4) TestAppA,Bそれぞれで、SubClassX.csをリンク参照に変更。

個人的には(2)~(3)に問題があるように思えるのですが、解決策が見つかりません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/08/29 09:45

こういう質問をするなら、何を作っているか(Winforms? WPF? その他?)と開発環境(OS, Visual Studio のバージョン、.NET Framework or Core どっちかとそのバージョン)ぐらいは書きませんか? TestAppA, TestAppB が Winforms プロジェクトで TestAppCommon がそれらを使っている? 何をやっているのですかね。想像の斜め上のことをしているような気がするのですが・・・
退会済みユーザー

退会済みユーザー

2021/08/29 10:38 編集

テンプレートはWindows Formアプリです。 Visual Studioのバージョンは2019でフレームワークは.Net Core3.1です。 (実際は.Net Framework 4.6.1ですが自宅では↑でした) TestAppCommmonは質問に書いたようにエクスプローラで作ったフォルダに.csを直接配置し、namespaceを二つのフォームとは異なる値に変えました。
退会済みユーザー

退会済みユーザー

2021/08/29 11:29

やっぱり想像の斜め上のこと、はっきり言うとメチャクチャなことをしてます。基本的なことを本を読むなどして一から勉強することをお勧めします。基本的な知識がないと、ここのような文章でやり取りするサイトでは話が通じなくて、お互い時間と労力の無駄に終わると思います。
退会済みユーザー

退会済みユーザー

2021/08/29 11:59 編集

クラス間の依存度が高すぎるので、正直プロジェクトを分けてメリットがある構成ではありません。
dodox86

2021/08/29 12:03

> SubClassX.csの中でFormA,FormBのインスタンスを と言う時点で、SubClassXクラスにとってFormAクラス、FormBクラスのそれぞれが部品であり、SubClassXからみて共通なものです。サブと言うより、FormAとFormBを管理する、上のレベルのクラスですね。
guest

回答5

0

正直,既存のやりとりを読んでも話を正確に把握できませんが,

どうやら,

  • FormA を表示したい場合 と FormB を表示したい場合 とがあり,どちらなのかは実行時に定まる.
  • で,そのことを「定める」方法として,コマンドライン引数やiniファイルを考えている.
  • exeは多重起動が防止されているから2つ起動させることができない.

という話になっていて,やりたいことは

【FormAを表示する形で実行したもの(プロセス) と FormBを表示する形で実行したもの(〃) とを同時に存在させたい】

であるように見える.
そうであるならば……

解1

「多重起動の防止」とかいう無意味な話をやめれば即座に解決するであろう.
あるいは,この防止の仕方を**「同じFormを表示する形態が」多重に存在することを防止する**形に改めればよかろう.

解2

単純に,

  • FormAを表示するアプリケーション
  • FormBを表示するアプリケーション

の2つを全く独立に作ればよいだけなのではないだろうか.
そうすればコマンドライン引数もiniファイルも不要であるし,多重起動がどうのいう話も回避できる.

「(起動する人から見ると)同じexeを実行している形」にすることに何かしらのこだわる理由あるのであれば,
「2つのexeのうちのどちら側を起動するのかをiniなりから決めて,それを起動するだけのexe」みたいなのを提供すればよかろう.


#質問のタイトルに関する話については既に回答が成されているので,ここでは触れない.

投稿2021/09/01 01:42

編集2021/09/01 01:43
fana

総合スコア11632

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

※僕の回答に対するコメントがありましたのでそちらの追加情報を加味して現時点でわかりうる条件を元に後ろに追記しています(2021/09/01 16:56)
質問者の回答へのコメントなどを見てもプログラミングへの理解が足りていないどころか、ソフトウェアを利用する利用者としても理解や知識が足りてないものと推測します

エントリポイント(Program.cs)への引数やiniファイルなんかでFormを使い分けて、Application.Runもそれぞれにありました。でもそれだとそれぞれの画面を実行する度にビルドが必要になりますよね。それを回避したかったのです。

要するにiniファイルにFormA,Bのどっちを表示するかを設定しておいても、実行する度にそこを書き換える必要があり、二つのexeが同時並行で存在しないと言いたかったんです。releaseでもdebugでも、フォルダ内にできるexeは一つです。そこに置いたままFormA,Bをそれぞれ表示するようにはできないですよね。

上記のコメントより推測すると、
起動時の引数やiniファイルの設定でFormAかFormBかを切り替えるというのと、
FormAとFormBの両方が表示される、つまり複数起動したいという事と、
恐らくはプロジェクトに含まれるiniファイルをビルド時にコピーされるのでiniファイルを変更した場合はビルドしないとだめなのだと思い込んでいる
と主張しているのだと思われます

そこから、まずは「iniファイルの内容が異なるものを複数用意したい」については、「ビルドして出来上がったフォルダの中身を任意のフォルダにコピーすればしてiniファイルをそれぞれ任意の値に編集すれば良い」で解決できます

次にiniファイルや起動時の引数で表示するフォームを切り分けたいのであれば、面倒なことはせずにとりあえず全部同じプロジェクトに入れてやり、普通に条件によってどのフォームを起動するのか切り分ける処理を書けばいいだけです
後はコピーしたそれぞれのフォルダの中にあるiniファイルを編集すればいいだけなので

とりあえず、多重起動を禁止する処理を書かない限りは実行ファイルを起動してから終了しないままもう一度実行ファイルを起動すればもう一つプログラムが起動できるという事を知らないんだと推測します

これが間違っていたら質問者さん以外の人に状況が理解できるようにやりたいことをまずは他の人にわかるように書いてください
あなた以外の人はあなたではありません
「ジュース買えなかったー、助けて」と言われてもお金がなかったのかジュースが売り切れていたのか、そもそもジュースが売られていない場所(宇宙空間等)に居るからなのかは何故買えなかったのかを書いてくれなければ本人や目撃者以外だと誰にもわかりません

2021/09/01 16:56追記分
本人がもう閉めてるので意味はなさそうやけど……

言い間違いという後に書いてあるのが以下の内容だったので直前のコメントとそのレスからビルドし直しと表現した内容の説明に当たると思って読んだけど内容見て違う話を書いてるのだと解釈してました

要するにiniファイルにFormA,Bのどっちを表示するかを設定しておいても、実行する度にそこを書き換える必要があり、二つのexeが同時並行で存在しないと言いたかったんです。releaseでもdebugでも、フォルダ内にできるexeは一つです。

多重起動禁止は僕の回答でようやく引き出せた内容です
にもかかわらず

自分としてもこれでもかというくらい分かりやすく説明しているつもり

とありますので、他にももっと漏れがあるだろうなという事は容易に推測できます

そのうえで以下の条件を元に自分ならどうするかを考えて見ます
・多重起動禁止
・単一フォルダのみの展開
・実行時にどの画面を表示するのかをiniファイルから判断するも、その都度iniファイルを書き換える

以下が思いついた自分なりの対処法
・画面はすべて同じプロジェクトに入れる
・質問文にあるSubClassXはマルチスレッドで待機して呼ばれるたびに多重起動チェックで引っかからなかったら内部で外部からの待ち受け(ソケットなりなんなりを使用する)を行っておき、起動引数を受け取れるようにしておく
引っかかったら起動済みの待ち受けに起動引数を投げて終了する
・待ち受けで受信するたびにiniファイルの情報を元に対象となる画面を表示する
別スレッドでUIだと面倒ごとが多いので画面表示はUIスレッドで行う

恐らくiniファイルは都度都度書き換える必要もなくオンメモリで良いと思う
UIスレッドと待ち受けスレッドの管理が面倒そうなので質問者が実装可能かどうかは考慮してない
いっそのこと画面ごとに別exeにしてしまってプロキシプログラムとして分離した方が管理が楽かもしれない

まだまだ提示されていない前提条件もあるかもしれないのでこれで解決できるかどうかは不明だけど、
現時点で提示された条件を元に作るなら自分ならこうするという内容を大雑把に書いてみた

投稿2021/08/30 16:35

編集2021/09/01 08:15
len_souko

総合スコア1337

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/08/31 15:00

すみません、自分としてもこれでもかというくらい分かりやすく説明しているつもりなので、何を書き足して欲しいのかが伝わってきません。 ・アプリの多重起動は禁止しています。 ・プロジェクトのReleaseフォルダ以下を提供しexeを起動してもらうだけの流れなので、勝手にフォルダを作る事はできません。 ・iniファイルの変更でビルドが必要と言った件は、言い間違いと訂正してるかと思います。 とりあえず、プロジェクトは別にして互いに影響しあわない部分だけを共通化する方向で検討を進めています。 「あなた以外の人はあなたではありません」 だから何ですか?そこまで上から目線で言われるのならもういいです。回答して来ないで下さい。自分の力だけでなんとかします。頼った私が馬鹿でした。
退会済みユーザー

退会済みユーザー

2021/08/31 16:12

その箇条書きにしてる事、一つも質問文に書いてないですよね。 いい年して、自身の説明不足を棚に上げて逆切れするのはみっともないですよ。
guest

0

ベストアンサー

なんか頼るのが馬鹿馬鹿しくなったので閉じます。
解決策はlen_soukoさんへの返信に書いています。

投稿2021/08/31 15:03

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まず、プロジェクトは循環参照出来ません。
SubClassXにFormAとFormB両方が入ってる時点で、これらのクラスは相互依存が発生し、もうプロジェクトの分割は不可能です。
プロジェクト設計とクラス設計を見直すべきでしょう。

投稿2021/08/29 12:18

編集2021/08/29 12:27
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

何をどう操作しているのかよくわかりませんけれど、参照できるのは『プロジェクト単位』です。

(2) 双方で共通のクラスSubClassXを新たに作成したTestAppCommonフォルダに移動。

共通クラスならば、共通用のクラスライブラリ(DLL)プロジェクトを作成しましょう。

ただし、私にはこのSubClassXがいわゆる『共通クラス』には見えません。
TestAppAとTestAppBの共通クラスというものは、TestAppAやTestAppBを参照するのではなくて、TestAppAやTestAppBから参照されるのです。

using TestAppA; using TestAppB;

こんなのが共通側にある時点で設計を間違えているんですよ。
双方向で参照が必要となってしまうならば、全部同じプロジェクトに入れましょう。

投稿2021/08/29 09:56

ishina_yum

総合スコア509

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/08/29 10:18

「全部同じプロジェクトに入れましょう。」 最初はそうしていました。エントリポイント(Program.cs)への引数やiniファイルなんかでFormを使い分けて、Application.Runもそれぞれにありました。でもそれだとそれぞれの画面を実行する度にビルドが必要になりますよね。それを回避したかったのです。
bboydaisuke

2021/08/29 10:48

> でもそれだとそれぞれの画面を実行する度にビルドが必要になりますよね。 「実行する度」にビルドが必要になるってどういうことですか?コードを変更したらビルドしないといけないのはわかりますけれども。何かいろいろと間違ったり勘違いしているようで、理解するのが難しく、多分お互いに正しく理解できてないと思います。他の方もわからないことを表明してますよね。
退会済みユーザー

退会済みユーザー

2021/08/29 12:35

すみません言い間違えました。 要するにiniファイルにFormA,Bのどっちを表示するかを設定しておいても、実行する度にそこを書き換える必要があり、二つのexeが同時並行で存在しないと言いたかったんです。releaseでもdebugでも、フォルダ内にできるexeは一つです。そこに置いたままFormA,Bをそれぞれ表示するようにはできないですよね。
Zuishin

2021/08/29 12:44

普通にできるでしょう。プログラムなんだから。
退会済みユーザー

退会済みユーザー

2021/08/29 12:59 編集

やりたい事に対して、実現するための手段が間違っている気がします。まずやりたい事を具体的に記述した方がよいのでは。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問