8

私はMEFを実験していて、次のような特定のインターフェイスを実装する「プラグイン」を呼び出すテストプログラムを作成しました。

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

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

独自のアセンブリから、および見つかった場合は追加のDLLを配置するディレクトリから「プラグイン」をロードするサンプルコンソールプログラムを作成しました。プラグインディレクトリが空であるか(「ネイティブ」プラグインのみが呼び出される)、または互換性のあるDLLがあるかどうかに関係なく、プログラムは正常に動作します。しかし...ループの反復の間に新しいDLLが追加されると、DirectoryCatalogのRefresh()メソッドはChangeRejectedExceptionをスローします。これは、次のように説明されます。

構成は変更されません。次のエラーのため、変更は拒否されました。コンポジションで単一のコンポジションエラーが発生しました。根本的な原因を以下に示します。詳細については、CompositionException.Errorsプロパティを確認してください。

1)パーツ「MEFTest.Program」の再構成不可能なインポート「MEFTest.Program.ProberSet(ContractName = "ProbeContract.IProbe")」によって防止されたエクスポートの変更。

プログラムは以下のとおりです。追加しようとしているDLLのコードが続きます。私は何が間違っているのですか?

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

プラグイン。他の2つのプラグインは類似していますが、唯一の違いは、メインプログラムと同じアセンブリに存在することです。

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

1 に答える 1

13

拒否の例外が表示されているため、MEFプレビュー6を使用していると想定しています。変更が拒否されているのが見える理由は、ProberSetが再構成できないためです。ProberSetのインポートを次のように変更してみてください。

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

そうすることで、このインポートがすでに作成された後、新しいIProbeエクスポートをカタログ/コンテナーに導入できるようになります。

ここでの考え方は、安定したコンポジションを取得すると、そのコンポジションを不安定にする可能性のある変更を拒否し、再構成不可能なIProbeオブジェクトのセットが必要であると述べたため、最初に設定された後に新しいIProbeを追加するとその要件に違反するということです。 。

于 2009-07-16T01:07:55.580 に答える