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

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

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

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

Q&A

解決済

1回答

4948閲覧

DependencyInjectionで、コンストラクタへのパラメータを動的に渡してインスタンスを作成したい

user111

総合スコア8

C#

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

0グッド

0クリップ

投稿2020/07/07 01:45

前提・実現したいこと

Microsoft.Extensions.DependencyInjectionを使用してDIを行おうとしています。
コンストラクタにパラメータを持つクラス(Sample)をForm1にInjectionしようとしているのですが
以下の記述だと呼び出し側で固定で値("abc")が設定されることになります。

この"abc"の値を、Form1側で動的に指定できないでしょうか?

Program

1[STAThread] 2private static void Main() 3{ 4 var serviceCollection = new ServiceCollection(); 5 serviceCollection.AddTransient<Form1>(); 6 // これで Sampleにパラメータ"abc"を渡してInjectionされる 7 serviceCollection.AddTransient<ISample, Sample>(_ => new Sample("abc")); 8 9 var provider = serviceCollection.BuildServiceProvider(); 10 11 Application.EnableVisualStyles(); 12 Application.SetCompatibleTextRenderingDefault(false); 13 Application.Run(provider.GetRequiredService<Form1>()); 14}

Form1

1using System.Windows.Forms; 2 3namespace WindowsFormsApp17 4{ 5 public partial class Form1 : Form 6 { 7 public Form1(ISample sample) 8 { 9 InitializeComponent(); 10 } 11 } 12 13 public class Sample : ISample 14 { 15 // パラメータが必要なコンストラクタ 16 public Sample(string str) 17 { 18 } 19 } 20 21 public interface ISample 22 { 23 } 24}

やりたいことのイメージ

以下、エラーになりますが、やりたいことのイメージです
Form1側でInjectionされた型にパラメータを渡し、インスタンス化を行っているイメージです。

Program

1[STAThread] 2private static void Main() 3{ 4 var serviceCollection = new ServiceCollection(); 5 serviceCollection.AddTransient<Form1>(); 6 // ここではinjectionされるクラスのみを指定 7 serviceCollection.AddTransient<ISample, Sample>(); 8 9 var provider = serviceCollection.BuildServiceProvider(); 10 11 Application.EnableVisualStyles(); 12 Application.SetCompatibleTextRenderingDefault(false); 13 Application.Run(provider.GetRequiredService<Form1>()); 14}

Form1

1using System.Windows.Forms; 2 3namespace WindowsFormsApp17 4{ 5 public partial class Form1 : Form 6 { 7 private readonly ISample _sample; 8 9 public Form1(ISample sample) 10 { 11 InitializeComponent(); 12 // なんらかの条件があり 13 if (xxx) 14 { 15 // ある場合は、パラメータ"abc"でインスタンス化 16 _sample = sample("abc"); 17 } 18 else 19 { 20 // ある場合は、パラメータ"efg"でインスタンス化 21 _sample = sample("efg"); 22 } 23 } 24 } 25 26 public class Sample : ISample 27 { 28 public Sample(string str) 29 { 30 } 31 } 32 33 public interface ISample 34 { 35 } 36}

よろしくおねがいします。

補足情報(FW/ツールのバージョンなど)

VisualStudio2017
.NetFramework4.7.2

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんにちは。

DI コンテナ側ではなく Form1 がパラメータを指定したいのであれば、Sample を注入する代わりに、その Factory を定義して注入すれば良いです。

csharp

1public interface ISampleFactory 2{ 3 ISample Create(string str); 4} 5 6public class SampleFactory 7{ 8 public ISample Create(string str) 9 => new Sample(str); 10}

csharp

1serviceCollection.AddSingleton<ISampleFactory, SampleFactory>();

あとはコンストラクタから使うだけです。

csharp

1public Form1(ISampleFactory sampleFactory) 2{ 3 InitializeComponent(); 4 // なんらかの条件があり 5 if (xxx) 6 { 7 // ある場合は、パラメータ"abc"でインスタンス化 8 _sample = sampleFactory.Create("abc"); 9 } 10 else 11 { 12 // ある場合は、パラメータ"efg"でインスタンス化 13 _sample = sampleFactory.Create("efg"); 14 } 15}

投稿2020/07/07 02:46

tamoto

総合スコア4110

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

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

user111

2020/07/07 12:37

なるほど、できました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問