Search code examples
c#unity-containermef

Unity and MEF cooperation


I am trying to implement basic module loading system in my application where I am using Unity to handle DI. I thought it would be easy to use FileSystemWatcher and MEF to add dynamic loading, but I ran in to a problem.

Intro

When registering directory with modules I read modules that are currently present in the directory and set up a FileSystemWatcher

public List<IModule> RegisterModule(string directoryUri){
        var fsw = new FileSystemWatcher(directoryUri, "*.dll");
        fsw.Created += OnModulesChange;
        fsw.EnableRaisingEvents = true;

        return GetModules();
}

In the handler I refresh the MEF directory catalogs and fire event notifying that the container has changed

private void OnModulesChange(object sender, FileSystemEventArgs e)
{
   _catalog.Catalogs.OfType<DirectoryCatalog>().ForEach(x => x.Refresh());
   ModuleDirectoryChanged?.Invoke(this);
   lastRead = DateTime.Now;
}

Every subscriber than reads new modules again through GetModules method:

public List<IModule> GetModules()
{
   var directories = _mefContainer.GetExports<IModule>().Select(x => x.Value).ToList();
   directories.ForEach(x => x.RegisterModule(this));
   return directories.Concat(_staticModules).ToList();
}

In the RegisterModule method I do some resolving with Unity. It is quite a lot of logic now but in the end the only related method I use there is this :

public T Resolve<T>() where T : class, IMyThing
{            
   return this._container.Resolve<T>();
}

Problem

When GetModules is called for the first time, everything works right (I just have the dll with module in the directory when running the application and register the directory on startup). I can place breakpoint to the Resolve method and see that everything is registered and the object is really resolved.

But when I copy another .dll to the directory, then I get ResolutionFailedException from Resolve method. If I look into the container I see the type Registrations as I did before. The same container is used, same methods is called, the only difference is that the call is initiated by the FileSystemWatcher.

What am I doing wrong ? It may be a systematic problem as I never used MEF and Unity together, and I have only limited knowledge of Unity.

Sorry if the description is confusing, I will try to clear any additional questions.

Versions

  • .NET 4.5.2
  • Unity 3.5 (also tried referencing cloned Unity repository so baseline version)
  • MEF directly from .NET 4.5.2 (not MEF 2)

Solution

  • These libraries can be used together and you might want to if you want DI and extensibility.

    The problem is that the Unity container and the MEF catalog/container are not aware of each other. Install the MefContrib.Integration.Unity on NuGet and you can make them work together using this code:

    // Setup
    var unityContainer = new UnityContainer();
    var aggregateCatalog = new AggregateCatalog();
    
    // Register catalog
    unityContainer.RegisterCatalog(aggregateCatalog);
    

    Read More...

    In a Prism application, you want to do this in the Bootstrapper as part of the CreateContainer override. Or MEF will not be able to resolve a lot of things that Prism provides to Unity, such as the IUnityContainer, IEventAggregator or IRegionManager.