Codeplexホームページから最新のMEF2プレビューを使用していますが、オープンジェネリックサポートが追加されることになっています。そうですが、この特定のケースでは、MEFはジェネリックインターフェイスのジェネリック実装を構成できません。
public interface IOuter
{
IInner Value { get; }
}
[Export(typeof(IOuter))]
public class MyOuter : IOuter
{
[ImportingConstructor]
public MyOuter(InnerGenericClass<string, int> value)
{
this.Value = value;
}
public IInner Value { get; private set; }
}
public interface IInner
{
void Say();
}
public interface IGenericInner<T, K> : IInner
{
// something else here
}
[Export(typeof(IGenericInner<,>))]
public class InnerGenericClass<T, K> : IGenericInner<T, K>
{
public void Say()
{
Console.WriteLine("{0}, {1}", typeof(T), typeof(K));
}
}
class Startup
{
public void CatalogSetup()
{
var catalog = new AggregateCatalog(
new AssemblyCatalog(Assembly.GetExecutingAssembly())
);
var container = new CompositionContainer(catalog, CompositionOptions.DisableSilentRejection);
var batch = new CompositionBatch();
container.Compose(batch);
var outer = container.GetExportedValue<IOuter>();
outer.Value.Say();
}
}
これがCompositionExpectionです:
The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) No exports were found that match the constraint:
ContractName ConsoleApplication1.InnerGenericClass(System.String,System.Int32)
RequiredTypeIdentity ConsoleApplication1.InnerGenericClass(System.String,System.Int32)
Resulting in: Cannot set import 'ConsoleApplication1.MyOuter.Value (ContractName="ConsoleApplication1.InnerGenericClass(System.String,System.Int32)")' on part 'ConsoleApplication1.MyOuter'.
Element: ConsoleApplication1.MyOuter.Value (ContractName="ConsoleApplication1.InnerGenericClass(System.String,System.Int32)") --> ConsoleApplication1.MyOuter --> AssemblyCatalog (Assembly="ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
Resulting in: Cannot get export 'ConsoleApplication1.MyOuter (ContractName="ConsoleApplication1.IOuter")' from part 'ConsoleApplication1.MyOuter'.
Element: ConsoleApplication1.MyOuter (ContractName="ConsoleApplication1.IOuter") --> ConsoleApplication1.MyOuter --> AssemblyCatalog (Assembly="ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
InnerGenericClassのインポートをMyOuter.Valueの属性に移動しても、同じ例外がスローされます。
[Export(typeof(IOuter))]
public class MyOuter : IOuter
{
[Import(typeof(InnerGenericClass<string, int>))]
public IInner Value { get; private set; }
}
奇妙なことに、インポートタイプをIGenericInnerに変更すると、機能します。
[Export(typeof(IOuter))]
public class MyOuter : IOuter
{
[ImportingConstructor]
public MyOuter(IGenericInner<string, int> value)
{
this.Value = value;
}
public IInner Value { get; private set; }
}
さらに奇妙なのは、属性を介してインポートすると機能しないことです。
概要:ジェネリックインターフェイスを使用してオブジェクトをValueプロパティにインポートすることはできません。これは、 IGenericInnerインターフェイスの実装がさらに存在する可能性があるためです(特定の実装をインポートしたいのですが、それは重要ではありません)。
この場合、MEFを完全にバイパスする必要がないことを願っています。