Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MEF Runtime Plugin Update Issue

Issue

My MEF code is not appropriately updating assemblies during runtime, from a folder associated to a DirectoryCatalog. The plugins load at run-time succesffully, but when i update the dll and call Refresh on the DirectoryCatalog, the assemblies are not getting updated.

Background

I am building a dll that has an MEF container, and uses a DirectoryCatalog to find a local plugin folder. I call this dll currently from a simple WinForm, that is setup to with a seperate project to use ShadowCopy so i can overwrite the dlls in my plugin folder. Instead of using a FileWatcher to update this folder, I am exposing a public method that calls refresh on the DirectoryCatalog, so i can update the assemblies at will instead of automatically.

Code

base class instantiates the MEF catalogs and container, and saves them as class variables for referential access later

    public class FieldProcessor
{
    private CompositionContainer _container;
    private DirectoryCatalog dirCatalog;

    public FieldProcessor()
    {
        var catalog = new AggregateCatalog();
        //Adds all the parts found in the same assembly as the TestPlugin class
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(TestPlugin).Assembly));
        dirCatalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory + "Plugin\\");
        catalog.Catalogs.Add(dirCatalog);

        //Create the CompositionContainer with the parts in the catalog
        _container = new CompositionContainer(catalog);
    }

    public void refreshCatalog()
    {
        dirCatalog.Refresh();
    }

} ...

here's the plugin i'm trying to overwrite. My test of updating, is that the stings returned are output to a text box, I change the Strings the plugin is returning, rebuild, and copy it in to the plugin folder. But it does not update for the running app, until i close and restart the app.

[Export(typeof(IPlugin))]
[ExportMetadata("PluginName", "TestPlugin2")]
public class TestPlugin2 : IPlugin
{
    public IEnumerable<IField> GetFields(ContextObject contextObject, params string[] parameters)
    {
        List<IField> retList = new List<IField>();
        //Do Work Return Wrok Results
        retList.Add(new Field("plugin.TestPlugin2", "TestPluginReturnValue2"));
        return retList;
    }
}

Edit

Import Statement
    [ImportMany(AllowRecomposition=true)]
    IEnumerable<Lazy<IPlugin, IPluginData>> plugins;

Research

I have done fairly extensive research and everywhere in articles and code samples the answer appears to be, to add a DirectoryCatalog to a container and save a reference of that catalog, then call Refresh on that reference, after a new plugin has bee added, and it will update the assemblies...which i am doing, but it's not showing updated output, from the new plugin dll.

Request

Has anyone seen this issue, or know what may be causing my problems with the assemblies not updating during runtime? Any additional information or insight would be appreciated.

Resolution

Thanks to Panos and Stumpy for their links which led me to the solution my issue. For future knowledge seekers, my main issue was that the Refresh method does not update assemblies, when the new assembly has the exact same assembly name as the overwritten dll. For my POC i just tested rebuilding with a Date appended to the assembly name and everything else the same, and it worked like a charm. their links in the comments below, were very useful, and are recommended if you have the same issue.
like image 702
Mabdullah Avatar asked Apr 22 '13 15:04

Mabdullah


1 Answers

did you set AllowRecomposition parameter to your Import attribut?

AllowRecomposition
Gets or sets a value that indicates whether the property or field will be recomposed when exports with a matching contract have changed in the container.

http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.importattribute(v=vs.95).aspx

edit:

DirectoryCatalog doesn't update assemblies, only added or removed: http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.hosting.directorycatalog.refresh.aspx

for a work around: https://stackoverflow.com/a/14842417/2215320

like image 191
Niels Avatar answered Oct 23 '22 22:10

Niels