Inky Quill
Inky Quill

Reputation: 43

MEF Import doesn't work as expected

I have two classes with exports:

[Export(typeof(Mod))]
public class CoreMod : Mod
{
    [ImportingConstructor]
    public CoreMod()
    {
      //here goes my constructor
    }
}

[Export(typeof(Mod))]
public class AnotherMod : Mod
{
    [ImportingConstructor]
    public AnotherMod()
    {
      //here goes my constructor
    }
}

CoreMod is in my main assembly, AnotherMod is in the external assembly. Mod is in yet another assembly, which they are both referencing.
In my app I have a class which tries to load Mods via MEF:

class ModManager
{
    [ImportMany(typeof(Mod))]
    public static IEnumerable<Mod> Mods { get; set; }

    public List<Mod> LoadedMods { get; set; } 

    public ModManager()
    {
        AggregateCatalog catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(CoreMod).Assembly));
        catalog.Catalogs.Add(new DirectoryCatalog(
            Path.GetDirectoryName(
                new Uri(Assembly.GetExecutingAssembly()
                               .CodeBase).LocalPath)));

        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);

        LoadedMods = Mods.ToList();
    }
}

Looks to me like all imports should be satisfied, but it still fails to import anything (Mods is null). What am I doing wrong?

Upvotes: 4

Views: 970

Answers (1)

Jacob Lambert
Jacob Lambert

Reputation: 7677

I think what is happening is that you have your CompositionContainer as a function variable instead of a class variable. Also, MEF does not support importing to a static variable. Try using this:

class ModManager
{
    [ImportMany(typeof(Mod))]
    public IEnumerable<Mod> Mods { get; set; }

    public List<Mod> LoadedMods { get; set; } 
    CompositionContainer _container;

    public ModManager()
    {
        AggregateCatalog catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(CoreMod).Assembly));
        catalog.Catalogs.Add(new DirectoryCatalog(
            Path.GetDirectoryName(
                new Uri(Assembly.GetExecutingAssembly()
                               .CodeBase).LocalPath)));

        _container = new CompositionContainer(catalog);
        this._container.ComposeParts(this);

        this.LoadedMods = this.Mods.ToList();
    }
}

Upvotes: 1

Related Questions