1

ITaggerとIWpfTextViewMarginがあり、どちらもMEFコンポーネントとしてエクスポートされます。マージンコードにITaggerをインポートしてから、そのTaggerでいくつかのメンバーを使用したいと思います。

ここで、MarginクラスでComponentContainerを使用してから、IViewTaggerProviderをインポートしようとしました。私は次のコードを使用しました。これは多くのMEFチュートリアルにあります。

[Import(typeof(IViewTaggerProvider))]
public IViewTaggerProvider vt_provider { get; set; }

var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(TestMargin).Assembly));
_container = new CompositionContainer(catalog);
//Fill the imports of this object
try
{
    this._container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
    System.Diagnostics.Trace.WriteLine(compositionException.Message);
}

およびエクスポートコード。

[Export(typeof(IViewTaggerProvider))]
[ContentType...

エクスポートされたクラスは別の名前空間で定義されていますが、同じアセンブリです。

ここで、ComposeParts(this)がImportCardinalityMismatchExceptionをスローするという問題が発生しました。パラメータがなぜこれなのかわかりません。カタログを渡そうとしましたが、例外はありませんが、インポートもnullです。また、デバッグmefの失敗についても言及し、エクスポートされたクラスには正しいコントラクト名とエクスポートタイプのIDがあると信じています。


Visual MEFxでアセンブリを確認してデバッグしたところ、おそらくIViewTaggerProviderがVisual Studio IClassificationTypeRegistryServiceをインポートしていることがわかりました。これもMEFパーツであり、IViewTaggerProviderが拒否されます。

[Primary Rejection]
 [Exception] System.ComponentModel.Composition.ImportCardinalityMismatchException: No valid exports were found that match the constraint '((exportDefinition.ContractName == "Microsoft.VisualStudio.Text.Classification.IClassificationTypeRegistryService") AndAlso (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") AndAlso "Microsoft.VisualStudio.Text.Classification.IClassificationTypeRegistryService".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))', invalid exports may have been rejected.

したがって、1つの解決策は、IClassificationTypeRegistryServiceをエクスポートするアセンブリを追加することです。これはVisualStudioコアエディターサービスですが、どのアセンブリがそれをエクスポートするかがわかりません。誰もがこれを知っていますか?

または、より良い解決策はありますか?

4

1 に答える 1

1

VisualMEFxをお試しください。これは、開始に関する短いブログエントリですhttps://ihadthisideaonce.com/2012/02/22/getting-started-with-visual-mefx/。起動して実行したら、VisualMEFxを使用してTestMarginアセンブリをロードし、そのアセンブリからIViewTaggerProviderがエクスポートされているかどうかを確認します。

また、ImportCardinalityMistmatchは、エクスポートが欠落していることを意味するだけではないことも覚えておいてください。また、インポートを満たすことができるエクスポートが多すぎて、MEFがどちらを使用するかを選択する方法がないことを意味する場合もあります。したがって、VisualMEFxで構成を調べるときは、構成が多すぎるかどうかを確認してください。

このパラメーター:

void Bootstrap()
{
  var catalog = new AggregateCatalog();
  catalog.Catalogs.Add(new AssemblyCatalog(typeof(TestMargin).Assembly));
  _container = new CompositionContainer(catalog);

 //Fill the imports of this object
 try
 {
    var objectToSatisfy = this;
    // var objectToSatifsy = new SomeOtherObjectWithImports();

    this._container.ComposeParts(objectToSatisfy);
 }
 catch (CompositionException compositionException)
 {
    System.Diagnostics.Trace.WriteLine(compositionException.Message);
 }
}

呼び出すComposePartsときは、オブジェクトをメソッドに渡します。MEFは、渡されたオブジェクトを取得し、満たす必要のあるインポートがあるかどうかを確認します。輸入品が見つかった場合は、カタログを調べて満足させようとします。任意のオブジェクトをメソッドに渡すことができますComposeParts。そこで、サンプルコードを少し変更して、2つの異なるオプションを表示しました。1つのオプションは、満たす必要のあるオブジェクトを作成し、それをコンテナに渡して作成することです。これは、コメントアウトされた行で私が行ったことvar objectToSatisfy = new SomeOtherObjectWithImports()です。ただし、作成するオブジェクトが、呼び出しているオブジェクトと同じである場合がよくあります。ComposeParts。したがって、コンテナに渡すために新しいオブジェクトを作成する必要はありません。すでにオブジェクトがあり、それへの参照が必要です。C#では、キーワードを使用して現在のオブジェクトインスタンスへの参照を取得できますthis(VB.NETではキーワードはMe)。したがって、を呼び出しているのと同じオブジェクトのインポートを満たしたい場合は、への引数として参照をComposeParts使用することでそれを行うことができます。thisComposeParts

メソッドの引数ComposePartsはパラメーター配列です。非公式には、これは、あなたが書くとき、あなたが書いたかのようcontainer.ComposeParts(this)に解釈されることを意味しますcontainer.ComposeParts(new object[] { this })。実際には、これは、次のように、一度に複数のオブジェクトをMEFに渡すことができることを意味します。

container.ComposeParts(this, objectToSatifsy, thirdObjectToCompose);

オブジェクト呼び出しComposePartsにインポートがない場合はthis、引数として使用しないでください。代わりに、作成するタイプのオブジェクトを作成し、それをメソッドに渡します。また、作成するすべてのパーツがアセンブリで使用可能でない限り、パーツをTestMargin提供するアセンブリ用にさらにAssemlbyCatalogを作成し、それらをAggregateCatalogに追加する必要があります。

于 2012-04-27T13:23:46.203 に答える