MEF 'The export is not assignable to type' error
Asked Answered
A

4

7

I have just started using MEF and have hit on an early problem.

I have an interface called DataService:

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

    List<String> GetPeople();
  }
}

There are 2 implementations of this interface, one for SQL Server and one for Oracle. Below is the Oracle implementation, SQL Server implementation is exactly the same.

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

The name and description properties are now defunct as I have replaced these with metadata. As you can see, they are very simple objects, I wanted to make sure I could get this to work before I started doing the hard work.

This is the code I am using to discover the assemblies:

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

This is the error that is produced:

The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.

1) The export 'DataAccess.Oracle (ContractName="DataAccess.IDataService")' is not assignable to type 'DataAccess.IDataService'.

Resulting in: Cannot set import 'MEFTest.Form1.services (ContractName="DataAccess.IDataService")' on part 'MEFTest.Form1'. Element: MEFTest.Form1.services (ContractName="DataAccess.IDataService") --> MEFTest.Form1

It doesn't seem to make any sense that it can't assign to the interface that it was designed for!

Once this problem is solved, my next issue is how to pick one and get an instance of it...

Anastatius answered 17/10, 2010 at 21:27 Comment(0)
I
8

It looks like two different versions of your contract assembly (the one with DataAccess.IDataService) are getting loaded. One is probably from your executable path and the other from your plugin path. I touch on this issue a bit in my blog post on How to Debug and Diagnose MEF Failures, and the MSDN page on Best Practices for Assembly Loading goes into more detail.

Inheritrix answered 17/10, 2010 at 23:41 Comment(2)
You were right Daniel, I had re-compiled IDataService for the projects containing the SQLServer and Oracle plugins, but was referencing an older version in the main app. I moved the IDataService in to a separate class library project and referenced that from all three projects and all works perfectly. Thanks alot.Anastatius
This is quite tedious problem. It is not enough to check just your exe project but also projects of all satellite assemblies it loads. In my case exe loaded projects of 50+ other satellite assemblies and I had a hard time tracking, which one causes this duplicate loading. If not a brilliant hint by Daniel, I dont know how much time I could spend resolving it.Aleida
B
1

Yet another cause:

Code:

interface IMyService
{
}

[Export(typeof(IMyService))]
class MyService
{
}

Message:

The export 'IMyService' is not assignable to type 'IMyService'.

Cause:

The MyService class does not implement the IMyService interface.

Banal answered 24/7, 2019 at 9:18 Comment(0)
H
0

For me this had a very simple fix.

Here's a link! that explains the root cause.

In my case, I locked my Assembly version down, but my file version travels. My nuget package ID matches my assembly file version.

Final result is that I can build continuously, create new nugets, and not have this MEF inteface problem.

Hogshead answered 8/7, 2015 at 13:42 Comment(0)
A
0

I must tell that I had such an error in completely idiotic context. Accidentally, I misplaced export directive and put it not on class but on a function inside class:

interface MyInterface
{
  void MyFunction();
}

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

Surprisingly, the code compiled very fine without any warnings. But then I ve spent hours trying to figure out why MEF fails on my silly misprint!

Aleida answered 29/5, 2016 at 13:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.