2013-02-19 76 views
2

我使用的是最新的MEF 2预览版本Codeplex homepage,它应该添加开放式泛型支持。确实如此,但在这种特殊情况下,MEF未能构成通用实现通用接口的:MEF 2无法导入泛型接口的通用实现

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; } 
} 

什么是更加古怪,是,它不起作用,导入时通过属性。

摘要:我不能使用通用接口导入对象财产,因为可能有IGenericInner接口的多种实现(也是我想导入具体的实现,但是这并不重要)。

我希望在这种情况下我不必绕过MEF。

回答

5

导致您的导出接口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)); 
    } 
} 

我只是在VS .NET 4.5的项目测试,这和它的作品。 Btw。 MEF 2已经在.NET 4.5中发布 - 如果可能,我建议使用框架的System.ComponentModel.Composition.dll部分,而不是预览版本。

UPDATE: 的第三种解决方案(其将与预览版本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)); 
    } 
} 
+0

不幸的是,我只用了4.0(请参阅问题标签)。预览版本中您的建议不起作用。我无法升级到4.5,因为我仍然有运行WinXP的客户端。 – mnn 2013-02-20 17:48:19

+0

恩,太糟糕了。我'增加了第三个选项。我尝试避免这种语法,但它解决了这个问题。 – Andreas 2013-02-21 08:46:32

+0

谢谢,但这确实看起来很丑。我想我不会在我的API的这个特定部分使用MEF。 – mnn 2013-02-22 22:57:41