MEFを使用してプラグインを検出してインスタンス化し、プロセスを可能な限り堅牢にしたいと考えています。特に、不適切に作成されたプラグインがホストや他のプラグインの実行に悪影響を与えることは望ましくありません。
残念ながらGetExportedValues()
、実装クラスのコンストラクターのいずれかからスローされた例外を使用すると、コンテナーが効果的に「汚染」され、すべての「適切な」実装が返されないことがわかりました。
次のコードはこれを示しています。
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
namespace MefPoisoning {
class Program {
static void Main(string[] args) {
var catalog = new TypeCatalog(
typeof(GoodImplementation),
typeof(BadImplementation));
using (var container = new CompositionContainer(catalog)) {
try {
var implementations =
container.GetExportedValues<IInterface>();
Console.WriteLine("Found {0} implementations",
implementations.Count());
}
catch (CompositionException e) {
Console.WriteLine(e.Message);
}
}
}
}
[InheritedExport]
public interface IInterface {
}
public sealed class GoodImplementation : IInterface {
}
public sealed class BadImplementation : IInterface {
public BadImplementation() {
throw new InvalidOperationException();
}
}
}
BadImplementation
コンストラクターから例外をスローするGetExportedValues()
と、例外がスローされるため、適切な実装さえ返されません。エラーは、根本的な問題がBadImplementation
コンストラクターによるものであることを明確に示しています。
The composition produced a single composition error. The root cause is
provided below. Review the CompositionException.Errors property for more
detailed information.
1) Operation is not valid due to the current state of the object.
Resulting in: An exception occurred while trying to create an instance
of type 'MefPoisoning.BadImplementation'.
...
[GetExports()
同様に失敗することに注意してください。ただし、後で、Lazy<IInterface>
戻り値がクエリされたときに失敗します]。
この明らかな制限を回避する方法はありますか?