请参阅下面的代码:方法测试运行两次,一次使用类型参数Foo,第二次使用类型参数
<Bar<Foo>>
在Inside Test方法中,我们检索T和ExportFactory的相同类型的导出值。 第一次调用传递确定。 第二次调用导致注释中的组合拒绝。请注意,在第二次调用第一个警报传递ok时,实例已创建。这种类型的ExportFactory创建失败......
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Diagnostics;
namespace MefExportFactoryBug
{
class Program
{
static void Main(string[] args)
{
var tc = new TypeCatalog(new []{typeof(Foo),typeof(Bar<>),typeof(ExportFactoryProvider<>)});
var cc = new CompositionContainer(tc, true);
Test<Foo>(cc);//Pass OK
Test<Bar<Foo>>(cc);// Exception below thrown
/*
A first chance exception of type 'System.ComponentModel.Composition.ImportCardinalityMismatchException' occurred in System.ComponentModel.Composition.dll
A first chance exception of type 'System.ComponentModel.Composition.ImportCardinalityMismatchException' occurred in System.ComponentModel.Composition.dll
A first chance exception of type 'System.ComponentModel.Composition.ChangeRejectedException' occurred in System.ComponentModel.Composition.dll
System.ComponentModel.Composition Warning: 1 : The ComposablePartDefinition 'MefExportFactoryBug.ExportFactoryProvider(MefExportFactoryBug.Bar(MefExportFactoryBug.Foo))' has been rejected. The composition remains unchanged. The changes were rejected because of the following error(s): The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) No exports were found that match the constraint:
ExportFactory of:
ContractName MefExportFactoryBug.Bar(MefExportFactoryBug.Foo)
RequiredTypeIdentity MefExportFactoryBug.Bar(MefExportFactoryBug.Foo)
RequiredCreationPolicy NonShared
Resulting in: Cannot set import 'MefExportFactoryBug.ExportFactoryProvider(MefExportFactoryBug.Bar(MefExportFactoryBug.Foo)).Factory (ContractName="System.ComponentModel.Composition.Contracts.ExportFactory")' on part 'MefExportFactoryBug.ExportFactoryProvider(MefExportFactoryBug.Bar(MefExportFactoryBug.Foo))'.
Element: MefExportFactoryBug.ExportFactoryProvider(MefExportFactoryBug.Bar(MefExportFactoryBug.Foo)).Factory (ContractName="System.ComponentModel.Composition.Contracts.ExportFactory") --> MefExportFactoryBug.ExportFactoryProvider({0}) --> TypeCatalog (Types='MefExportFactoryBug.Foo, MefExportFactoryBug.Bar({0}), ...').
*/
}
private static void Test<T1>(ExportProvider cc) where T1:class
{
var ev = cc.GetExportedValue<T1>();
Debug.Assert(ev != null);
var ef = cc.GetExportedValue<ExportFactoryProvider<T1>>().Factory;
Debug.Assert(ef != null);
}
}
[Export]
public class ExportFactoryProvider<T>
{
[Import]
public ExportFactory<T> Factory { get; set; }
}
[Export]
public class Foo
{
}
[Export]
public class Bar<T>
{
}
}
答案 0 :(得分:0)
我找到了一个解决方法:在ExportFactoryProvider中使用SatisfyImportOnce可以解决问题并创建了ExportFactory。见下面的代码。仍然不确定为什么出口有,但ExportFactory不在原始问题的代码中......
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Diagnostics;
namespace MefExportFactoryBug
{
class Program
{
static void Main(string[] args)
{
var tc = new TypeCatalog(new []{typeof(Foo),typeof(Bar<>),typeof(ExportFactoryProvider<>)});
var cc = new CompositionContainer(tc, true);
Test<Foo>(cc);//Pass OK
Test<Bar<Foo>>(cc);//Pass OK now
}
private static void Test<T1>(CompositionContainer cc) where T1:class
{
var ev = cc.GetExportedValue<T1>();
Debug.Assert(ev != null);
var ef = new ExportFactoryProvider<T1>(cc).Factory;
Debug.Assert(ef != null);
}
}
[Export]
public class ExportFactoryProvider<T>
{
public ExportFactoryProvider(ICompositionService cc)
{
cc.SatisfyImportsOnce(this);
}
[Import]
public ExportFactory<T> Factory { get; set; }
}
[Export]
public class Foo
{
}
[Export]
public class Bar<T>
{
}
}