MEFのコンストラクターインジェクション属性を理解しようとしています。コンストラクターのパラメーターをロードするように指示する方法がわかりません。
これは私がロードしようとしているプロパティです
[ImportMany(typeof(BUsers))]
public IEnumerable<BUsers> LoadBUsers { get; set; }
アセンブリのインポートに使用するコードは次のとおりです。
try
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog("DI"));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
これが私がロードしようとしているクラスです
[Serializable]
[Export(typeof(BUsers))]
public class EditProfile : BUsers
{
[ImportingConstructor]
public EditProfile(string Method, string Version)
{
Version = "2";
Action = "Edit";
TypeName = "EditProfile";
}
ImportingConstructor属性を使用すると、コンストラクターのパラメーターがインポートになります。デフォルトでは、インポートするもの(契約名)は、インポート先のパラメーターまたはプロパティのタイプに基づいています。したがって、この場合、両方のインポートのコントラクトタイプは文字列であり、最初のパラメーターと2番目のパラメーターの間に実際の違いはありません。
インポートを使用して構成値を提供しようとしているようですが、これは必ずしも設計されたものではありません。これを希望どおりに実行するには、次のように、各パラメーターのコントラクト名をオーバーライドする必要があります。
[ImportingConstructor]
public EditProfile([Import("Method")] string Method, [Import("Version")] string Version)
{ }
次に、メソッドとバージョンをコンテナにエクスポートする必要があります。これを行う1つの方法は、それらを直接追加することです。
var container = new CompositionContainer(catalog);
container.ComposeExportedValue("Method", "MethodValue");
container.ComposeExportedValue("Version", "2.0");
container.ComposeParts(this);
(ComposeExportedValueは、実際には静的なAttributedModelServicesクラスで定義された拡張メソッドであることに注意してください。)
ある種の構成ファイルからこれらの値を読み取る場合は、構成を読み取り、その値をコンテナーへのエクスポートとして提供する独自のエクスポートプロバイダーを作成できます。
これを処理する別の方法は、構成値に名前でアクセスできるインターフェースをインポートし、コンストラクターの本体から必要な値を取得することです。
私はダニエルの解決策が好きです。ただし、私が目にする唯一のことは、カスタマイズされたCTORの[ImportingConstructor]を使用して、アクター(CompopositionContrainer()を作成する)とエクスポートパーツの間のパラメーター名の密結合です。たとえば、「メソッド」は両方で一致します。アクターとエクスポートパーツが異なるプロジェクトにある場合、エクスポートパーツのメンテナンスが難しくなります。
可能であれば、2番目のCTORをエクスポートパーツクラスに追加します。例えば:
[Export(typeof(BUsers))]
public class EditProfile : BUsers
{
[ImportingConstructor]
public EditProfile(EditProfileParameters ctorPars)
: this(ctorPars.Method, ctorPars.Version) {}
public EditProfile(string Method, string Version)
{
Version = "2";
Action = "Edit";
TypeName = "EditProfile";
}
EditProfileParametersのクラスは単純である必要があります:メソッドとバージョンの2つのプロパティ:
[Export]
public class EditProfileParameters{
public string Method { get; set; }
public string Version { get; set; }
}
重要な点は、Export属性をクラスに追加することです。次に、MEFはこのクラスをEditProfileのCTORのパラメーターにマップできるはずです。
次に、エクスポートパーツをコンテナに追加する例を示します。
var container = new CompositionContainer(catalog);
var instance1 = new EditProfileParameters();
// set property values from config or other resources
container.ComposeExportedValue(instance1);
container.ComposeParts(this);
ゲームに遅れましたが、MEFのあまり知られていない機能を活用する別のアプローチがあります。プロパティのエクスポート
public class ObjectMother
{
[Export]
public static EditProfile DefaultEditProfile
{
get
{
var method = ConfigurationManager.AppSettings["method"];
var version = ConfigurationManager.AppSettings["version"];
return new EditProfile(method,version);
}
}
}
これが機能するためにObjectMotherを使用する必要はなく、EditProfileに属性は必要ありません。