0

需求——

  1. 声明同一接口的共享导出。出口标有独特的出口名称,因此消费者可以进口特定风味的出口产品。
  2. 将类的公共实例注入一组对象,但不跨对象集共享公共实例[这使我使用不同的键使用共享导出-一组对象可以使用单个键来满足它们的共享导入需要]

这是导出类

public interface IMyExport
{
    void Display();
}

public class MyExport : IMyExport
{
    private Guid _id = Guid.NewGuid();

    public void Display()
    {
        Console.WriteLine("Instance ID = "+_id);
    }
}

这是我如何导出类的实例

public static class ExportInitialization
{
    [Export("Type A", typeof(IMyExport)),
    Export("Type B", typeof(IMyExport))]
    public static IMyExport IceCreamExport
    {
        get
        {
            return new MyExport();
        }
    }
}

消费者可以通过以下方式导入特定实例

[Export]
public class ImporterA
{
    private readonly IMyExport _myExport;

    [ImportingConstructor]
    public ImporterA([Import("Type A")]IMyExport myExport)
    {
        _myExport = myExport;
    }

    public void Display()
    {
        _myExport.Display();
    }
}

[Export]
public class ImporterB
{
    private readonly IMyExport _myExport;

    [ImportingConstructor]
    public ImporterB([Import("Type B")]IMyExport myExport)
    {
        _myExport = myExport;
    }

    public void Display()
    {
        _myExport.Display();
    }
}

class Program
{
    [Import]
    public ImporterA ImporterA { get; set; }

    [Import]
    public ImporterB ImporterB { get; set; }

    static void Main(string[] args)
    {
        new Program().Run();
    }

    public void Run()
    {
        var container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
        container.ComposeParts(this);

        ImporterA.Display();
        ImporterB.Display();

        Console.ReadKey();
    }
}

这曾经与 .Net 4.0 一起正常工作,但是当安装 .Net 4.5 时 - 我得到以下输出

Instance ID = 78bba41a-0c48-44fc-ae69-f0ead96371f9
Instance ID = 78bba41a-0c48-44fc-ae69-f0ead96371f9

请注意,两个导入都返回了相同的对象实例。我是否违反了一些关于通过静态属性导出的未记录规则?

4

2 回答 2

1

我发现从两个不同的静态属性导出特定实例可确保返回 2 个不同的实例。

    [Export("Type A", typeof(IMyExport))]
    public static IMyExport ExportA
    {
        get
        {
            return new MyExport();
        }
    }

    [Export("Type B", typeof(IMyExport))]
    public static IMyExport ExportB
    {
        get
        {
            return new MyExport();
        }
    }

这令人费解,因为在未修改的版本中,静态 getter 在每次获取时都会创建一个新实例。不确定这是否是 4.5 引入的某些 C#/.Net 优化的结果,或者这是否是 MEF 问题

于 2013-02-25T10:04:53.070 回答
0

这与MEF 部件的使用寿命有关。

MEF 属性的默认设置是组件不会说明它们是否每次都关心获取新实例。

意思是:

  • ExportAttribute没有指定是否可以或应该共享导出的实例;
  • 两个ImportAttributes 都没有指定是否应该共享它们的导入;

MEF 的默认行为是,如果不禁止共享实例,则它会。这意味着,根据文档,.NET 4.5 的行为是正确的:实例MyExport是共享的,因为双方都没有明确禁止共享。

我认为 .NET 4.0 存在每次调用静态属性的错误/差异,这导致了您观察到的情况,即非共享实例。而你依赖于那个错误。我认为这个错误的根源在于对属性的基本的、框架范围的期望——让静态属性为每个属性调用创建一个新的、语义上不同的实例是非常不寻常的。

我相信你应该:

  1. 将您的静态属性导出替换为静态方法导出;
  2. 在导出端或导入端将创建策略指定为非共享;
于 2013-02-25T09:50:43.307 回答