2010-10-17 17 views
5

Je viens de commencer à utiliser MEF et j'ai rencontré un problème au début.MEF 'L'exportation n'est pas affectable au type' erreur

J'ai une interface appelée DataService:

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

    List<String> GetPeople(); 
    } 
} 

Il y a 2 implémentations de cette interface, un pour SQL Server et un pour Oracle. Ci-dessous l'implémentation Oracle, l'implémentation de SQL Server est exactement la même.

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

Les propriétés de nom et de description sont maintenant défunte comme je l'ai remplacé ces métadonnées. Comme vous pouvez le voir, ce sont des objets très simples, je voulais m'assurer que je pourrais le faire fonctionner avant que je commence à travailler dur.

C'est le code que je utilise pour découvrir les assemblées:

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

Ceci est l'erreur qui est produite:

La composition produit une seule erreur de composition. La cause première est fournie ci-dessous. Consultez la propriété CompositionException.Errors pour plus d'informations.

1) L'exportation 'DataAccess.Oracle (ContractName = "DataAccess.IDataService")' n'est pas assignable pour taper 'DataAccess.IDataService'. Résultant de: Impossible d'initialiser 'MEFTest.Form1.services (ContractName = "DataAccess.IDataService")' sur la partie 'MEFTest.Form1'. Element: MEFTest.Form1.services (ContractName = « DataAccess.IDataService ») -> MEFTest.Form1

Il ne semble pas avoir de sens qu'il ne peut pas attribuer à l'interface qu'il a été conçu pour !

Une fois ce problème résolu, ma question suivante est de savoir comment choisir un et d'obtenir une instance de celui-ci ...

Répondre

6

Il ressemble à deux versions différentes de votre ensemble de contrat (celui avec DataAccess.IDataService) sont être chargé. L'un provient probablement de votre chemin exécutable et l'autre de votre chemin d'extension. Je touche un peu à ce problème dans mon blog sur How to Debug and Diagnose MEF Failures, et la page MSDN sur Best Practices for Assembly Loading va plus en détail.

+0

Vous aviez raison Daniel, j'avais recompilé IDataService pour les projets contenant les plugins SQLServer et Oracle, mais référençait une ancienne version dans l'application principale. J'ai déplacé l'IDataService dans un projet de bibliothèque de classes séparé et référencé cela à partir des trois projets et tout fonctionne parfaitement. Merci beaucoup. – hermiod

+0

C'est un problème assez fastidieux. Il ne suffit pas de vérifier uniquement votre projet exe mais aussi les projets de tous les assemblages satellites qu'il charge. Dans mon cas exe chargé des projets de plus de 50 autres assemblées de satellites et j'ai eu du mal à suivre, ce qui provoque ce chargement en double. Si ce n'est pas un indice brillant de Daniel, je ne sais pas combien de temps je pourrais y consacrer. –

0

Pour moi, cela avait une solution très simple.

Voici a link! cela explique la cause profonde.

Dans mon cas, j'ai verrouillé ma version d'assemblage, mais la version de mon fichier se déplace. Mon ID de paquet de nuget correspond à ma version de fichier d'assemblage.

Le résultat final est que je peux construire en continu, créer de nouveaux pépites, et ne pas avoir ce problème d'interface MEF.

0

Je dois dire que j'ai eu une telle erreur dans un contexte complètement idiot. Accidentellement, j'égaré directive à l'exportation et le mettre pas la classe mais sur une fonction à l'intérieur classe:

interface MyInterface 
{ 
    void MyFunction(); 
} 

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

Étonnamment, le code compilé très bien sans aucun avertissement. Mais j'ai passé des heures à essayer de comprendre pourquoi MEF échoue sur mon faute d'écriture!