Appel Refresh () sur un DirectoryCatalog lance ChangeRejectedException si de nouvelles DLL trouvées dans le répertoire

StackOverflow https://stackoverflow.com/questions/1133438

  •  16-09-2019
  •  | 
  •  

Question

J'expérimente avec et a créé MEF un programme de test pour appeler « plugins » qui mettent en œuvre une interface donnée , ce qui suit:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProbeContract
{
    public interface IProbe
    {
        int DoProbe(string what);
        List<string> GetCapabilities();
    }
}

J'ai créé un programme de console d'échantillon qui charge les « plugins » de sa propre assemblée et, le cas échéant trouvé, d'un diretory dans lequel on met des DLL supplémentaires. Le programme fonctionne sur OK si le répertoire plugins est vide (seuls les plug-ins « natifs » sont appelés) ou il a DLLs compatible pour commencer. Mais ... si une nouvelle DLL est ajouté entre les itérations de la boucle, la méthode Refresh () de DirectoryCatalog jette un ChangeRejectedException, qui est expliqué ainsi:

  

La composition reste inchangée. le   des modifications ont été rejetées en raison du   erreur suivant (s): La composition   produit une seule erreur de composition.   La cause racine est fournie ci-dessous.   Passez en revue les CompositionException.Errors   pour plus de détails propriété   informations.

     

1) Variation des exportations empêché par   importation non recomposable   « MEFTest.Program.ProberSet   (ContractName = "ProbeContract.IProbe") »   sur une partie 'MEFTest.Program'.

Le programme est ci-dessous, suivez par le code de la DLL j'essaie d'ajouter. Qu'est-ce que je fais mal?

using System;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProbeContract;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;

namespace MEFTest
{
    class Program
    {
        [ImportMany]
        IEnumerable<IProbe> ProberSet { get; set; }

        CompositionContainer exportContainer;
        DirectoryCatalog pluginCatalog;
        AggregateCatalog catalog;

        private void Run()
        {
            catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            string myExecName = Assembly.GetExecutingAssembly().Location;
            string myPath = Path.GetDirectoryName(myExecName);
            pluginCatalog = new DirectoryCatalog(myPath + "/Plugins");
            catalog.Catalogs.Add(pluginCatalog);
            exportContainer = new CompositionContainer(catalog);

            CompositionBatch compBatch = new CompositionBatch();
            compBatch.AddPart(this);
            compBatch.AddPart(catalog);
            exportContainer.Compose(compBatch);

            for (; ; )
            {
                Console.Write("Press any key to run all probes: ");
                Console.ReadKey(true);
                Console.WriteLine();
                pluginCatalog.Refresh();
                foreach (var Prober in ProberSet)
                {
                    Prober.DoProbe("gizmo");
                }
            }
        }

        static void Main(string[] args)
        {
            Program p = new Program();
            p.Run();
        }
    }
}

Le plug-in. Les deux autres plug-ins sont similaires, la seule différence étant qu'ils résident dans le même ensemble que le programme principal:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using ProbeContract;

namespace OtherProbes
{
    [Export(typeof(IProbe))]
    public class SpankyNewProber : IProbe
    {
        public int DoProbe(string what)
        {
            Console.WriteLine("I'm Spanky and New and I'm probing [{0}]", what);
            return 0;
        }

        public List<string> GetCapabilities()
        {
            List<string> retVal = new List<string>();
            retVal.Add("spanky");
            retVal.Add("new");
            return retVal;
        }
    }
}
Était-ce utile?

La solution

Je suppose que vous utilisez aperçu 6 parce que MEF vous voyez des exceptions de rejet. La raison pour laquelle vous voyez le changement est d'être rejeté parce que votre ProberSet ne recomposable. Essayez de changer votre importation ProberSet à:

[ImportMany(AllowRecomposition=true)]        
IEnumerable<IProbe> ProberSet { get; set; }

Cela permettra de nouvelles exportations de iProbe à introduire dans le catalogue / conteneur après cette importation a déjà été composé.

L'idée ici est qu'une fois que vous obtenez une composition stable, nous rejetons toute modification qui pourrait potentiellement déstabiliser cette composition et dans votre cas, vous avez dit que vous voulez un ensemble de non-recomposable iProbe objets afin d'ajouter de nouveaux iProbe de après avoir été intially réglée serait violation de cette exigence.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top