mnn*_*mnn 2 c# generics mef .net-4.0
我正在使用Codeplex主页上的最新MEF 2预览版,它应该添加开放式泛型支持.确实如此,但在这种特定情况下,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();
}
}
Run Code Online (Sandbox Code Playgroud)
这是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")
Run Code Online (Sandbox Code Playgroud)
即使我将InnerGenericClass的导入移动到MyOuter.Value的属性,也会抛出相同的异常:
[Export(typeof(IOuter))]
public class MyOuter : IOuter
{
[Import(typeof(InnerGenericClass<string, int>))]
public IInner Value { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
有什么奇怪的,当我将导入类型更改为IGenericInner时,它确实有效:
[Export(typeof(IOuter))]
public class MyOuter : IOuter
{
[ImportingConstructor]
public MyOuter(IGenericInner<string, int> value)
{
this.Value = value;
}
public IInner Value { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
什么是更奇怪的是,当通过属性导入时,它不起作用.
简介:我不能使用通用接口将对象导入Value属性,因为可能有更多的IGenericInner接口实现(我也想导入一个特定的实现,但这并不重要).
我希望在这种情况下我不必完全绕过MEF.
导致您导出接口IGenericInner <>但是要导入特定类InnerGenericClass MEF找不到正确的部分.您可以这样导出和导入特定类或创建两个InnerGenericClass <>导出:
[Export(typeof(IGenericInner<,>))]
[Export(typeof(InnerGenericClass<,>))]
public class InnerGenericClass<T, K> : IGenericInner<T, K> {
public void Say() {
Console.WriteLine("{0}, {1}", typeof(T), typeof(K));
}
}
Run Code Online (Sandbox Code Playgroud)
我刚刚在VS .NET 4.5项目中对此进行了测试,它确实有效.顺便说一句.MEF 2已经在.NET 4.5中发布 - 如果可能,我建议使用框架的System.ComponentModel.Composition.dll部分而不是预览版本.
更新:第三个解决方案(将与预览版本5一起使用)可能是另外使用字符串合同名称.我个人试图避免这种丑陋的语法原因,但没关系.代码将如下所示:
[Export(typeof(IOuter))]
public class MyOuter : IOuter {
[ImportingConstructor]
public MyOuter([Import("MySpecialInnerGenericClass", typeof(IGenericInner<,>))]InnerGenericClass<string, int> value) {
this.Value = value;
}
public IInner Value { get; private set; }
}
[Export("MySpecialInnerGenericClass", typeof(IGenericInner<,>))]
public class InnerGenericClass<T, K> : IGenericInner<T, K> {
public void Say() {
Console.WriteLine("{0}, {1}", typeof(T), typeof(K));
}
}
Run Code Online (Sandbox Code Playgroud)