2010-10-17 52 views
5

我刚开始使用MEF并遇到了一个早期问题。MEF'输出不能分配类型'错误

我有一个名为DataService的接口:

namespace DataAccess 
{ 
    interface IDataService 
    { 
    string Name { get; } 
    string Description { get;} 

    List<String> GetPeople(); 
    } 
} 

有2个实现此接口,一个用于SQL Server和一个用于Oracle。 下面是Oracle的实现,SQL Server的实现是完全一样的。

namespace DataAccess 
{ 
[Export(typeof(IDataService))] 
[ExportMetadata("Name","Oracle")] 
[ExportMetadata("Description","Oracle Data Service")] 
public class Oracle : IDataService 
{ 

    #region IDataService Members 

    public string Name 
    { 
     get { return "Oracle"; } 
    } 

    public string Description 
    { 
     get { return "Provides data access to Oracle database"; } 
    } 

    public List<string> GetPeople() 
    { 
     return new List<String>() { "Oracle boo", "Oracle boo1" }; 
    } 

    #endregion 
} 
} 

名称和说明属性现在已不存在,因为我用元数据替换了这些属性。正如你所看到的那样,它们是非常简单的对象,我想确保在开始努力工作之前,我可以把它做好。

这是我使用来发现组件的代码:

private static CompositionContainer _container; 
    private const string ASSEMBLY_PATTERN = "*.dll"; 
    private AggregateCatalog _catalog; 

    [ImportMany] 
    IEnumerable<DataAccess.IDataService> services { get; set; } 

    private void button3_Click(object sender, EventArgs e) 
    { 


     _catalog = new AggregateCatalog(
      new DirectoryCatalog(txtLibPath.Text, ASSEMBLY_PATTERN), 
      new AssemblyCatalog(Assembly.GetExecutingAssembly())); 
     _container = new CompositionContainer(_catalog); 
     _container.ComposeParts(this); 
     MessageBox.Show(services.Count().ToString()); 
    } 

这是所产生的误差:

该组合物生产的单一组合物的错误。根源在下面提供。查看CompositionException.Errors属性以获取更多详细信息。

1)导出'DataAccess.Oracle(ContractName =“DataAccess.IDataService”)'不可分配为键入'DataAccess.IDataService'。

导致:无法在部件'MEFTest.Form1'上设置导入'MEFTest.Form1.services(ContractName =“DataAccess.IDataService”)'。 元素:MEFTest.Form1.services(ContractName =“DataAccess.IDataService”) - > MEFTest.Form1

似乎没有任何意义,它不能分配给它设计的接口!

一旦这个问题解决了,我的下一个问题是如何选择一个,并得到它的一个实例...

回答

6

它看起来像两个不同版本的合同总成(带有DataAccess.IDataService)是正在加载。一个可能来自您的可执行路径,另一个来自您的插件路径。我在How to Debug and Diagnose MEF Failures的博客文章中详细讨论了这个问题,Best Practices for Assembly Loading上的MSDN页面更详细。

+0

你说得对Daniel,我为包含SQLServer和Oracle插件的项目重新编译了IDataService,但是在主应用程序中引用了旧版本。我将IDataService移动到一个单独的类库项目中,并引用了所有三个项目,并且都完美地工作。非常感谢。 – hermiod 2010-10-18 20:31:25

+0

这是一个相当乏味的问题。仅仅检查你的EXE项目是不够的,而且还要检查它加载的所有卫星组件的项目。在我的情况下exe加载50个其他卫星程序集项目,我很难跟踪,哪一个导致这种重复加载。如果丹尼尔不是一个精彩的提示,我不知道我可以花多少时间来解决它。 – 2016-05-29 09:41:31

0

对我来说,这有一个非常简单的修复。

Here's a link!这解释了根本原因。

在我的情况下,我锁定了我的Assembly版本,但是我的文件版本正在传播。我的nuget软件包ID与我的程序集文件版本相匹配。

最终的结果是,我可以连续构建,创建新的nugets,并且不存在此MEF接口问题。

0

我必须告诉我在完全愚蠢的情况下有这样的错误。一不留神,我忘记了出口的指令,并把它放在不是类,但在函数内部类:

interface MyInterface 
{ 
    void MyFunction(); 
} 

public class MyClass : MyInterface 
{ 
    [Export(typeof(MyInterface))] 
    void MyFunction() { } 
} 

出人意料的是,代码编译非常精细,没有任何警告。但后来我花了数小时试图弄清楚为什么MEF在我的愚蠢印刷错误上失败!

相关问题