1

外部機器 (I/O デバイス、オシロスコープ、波形発生器など) へのプラグイン インターフェイスに MEF を使用するアプリケーションを開発しています。これらのインターフェイスのほとんどは、機器にアクセスするために DLL を必要とし、可能であれば、これらの DLL をプラグインを含むプロジェクトにパックします。

アプリケーションはImportMany、プラグイン インターフェイスを実装するすべてのクラスをロードするために使用します。その後、ユーザーは必要なインターフェースを選択できます。

問題を引き起こしているインターフェイスが 1 つあります。すべての依存関係を特定できていません。別のワークステーションでアプリケーションを起動すると、未解決の依存関係エラーが発生します。すべてのドライバーとサポート DLL をインストールすると、問題なく動作するはずです。

ただし、すべてのユーザーがこの特定のインターフェイスを使用する必要があるわけではなく、すべてのワークステーションにすべてのドライバーをインストールしたくありません。一部の MEF プラグインをロードできない場合に適切に機能を低下させる方法を探しています。インターフェイスをロードできなかったことを通知するには、ログ メッセージで十分です。インターフェイス関数を使用しようとしている人だけがエラーを受け取るはずです。

ここに私のローダーコードがあります:

try
{
    var catalog = new AggregateCatalog();
    var container = new CompositionContainer(catalog);
    var batch = new CompositionBatch();
    batch.AddPart(this);
    catalog.Catalogs.Add(new AssemblyCatalog(typeof (Pruef.Net.TgtManager.TargetManager).Assembly));
    container.Compose(batch);

    _targets = _targets.OrderBy(t => t.DisplayName);
}
catch (Exception x)
{
    log.Error(x);
}
4

2 に答える 2

2

AllowDefaultImport 属性のプロパティを使用してみてください。

[Import(AllowDefault=true)]

ドキュメントから:

コントラクト名を持つエクスポートがコンテナーに存在しない場合に、プロパティ、フィールド、またはパラメーターがその型の既定値に設定されるかどうかを示す値を取得または設定します。

注: 作成時にスローと例外をプラグインすると、アプリケーションは引き続き失敗します。ドライバーが見つからないという例外は引き続き処理する必要があります。

于 2013-11-15T09:48:48.723 に答える
1

これは、エラーを回避するために行ったことです。正しい方向に向けてくれた@Gusdorに感謝します。遅延読み込みが有効なようです。

public class TargetManager
{
    private static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    [ImportMany(typeof(Pruef.Net.Contracts.ITarget))]
    private IEnumerable<Lazy<Pruef.Net.Contracts.ITarget>> _targets;

    public IEnumerable<Pruef.Net.Contracts.ITarget> AvailableTargets
    {
        get;
        private set;
    }

    /// <summary>
    /// Load all known target definitions
    /// </summary>
    public void Init()
    {
        try
        {
            var catalog = new AggregateCatalog();
            var container = new CompositionContainer(catalog);
            var batch = new CompositionBatch();
            batch.AddPart(this);
            catalog.Catalogs.Add(new AssemblyCatalog(typeof(Pruef.Net.TgtManager.TargetManager).Assembly));
            container.Compose(batch);

            List<ITarget> result = new List<ITarget>();
            foreach (Lazy<ITarget> t in _targets)
            {
                try
                {
                    result.Add(t.Value);
                }
                catch (Exception x)
                {
                    // could not load plugin
                    // log error and continue
                    log.Error(x);
                }
            }
            result = result.OrderBy(t => t.DisplayName).ToList();
            AvailableTargets = result;
        }
        catch (Exception x)
        {
            log.Error(x);
        }
    }
}

}

于 2013-11-15T12:21:46.613 に答える