MEF:为通用类型Bar <foo> </foo> </t>撰写ExportFactory <t>时的合成拒绝

时间:2014-07-28 15:38:10

标签: mef

请参阅下面的代码:方法测试运行两次,一次使用类型参数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>
    {
    }
}

1 个答案:

答案 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>
{
}

}