Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MEF 'The export is not assignable to type' error

Tags:

c#

mef

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

like image 815
hermiod Avatar asked Oct 17 '10 21:10

hermiod


2 Answers

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.

like image 169
Daniel Plaisted Avatar answered Nov 09 '22 15:11

Daniel Plaisted


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.

like image 24
Antonín Procházka Avatar answered Nov 09 '22 15:11

Antonín Procházka