我正在使用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>
会在查询其返回值时]。
有什么办法可以解决这个明显的限制吗?