.net MEF如何获取非共享实例引用

.net MEF如何获取非共享实例引用,.net,wpf,prism,mef,.net,Wpf,Prism,Mef,最近,我在WPF应用程序中使用MEF时遇到了一个问题。我创建了几个类,如下所示部分类型设置为CreationPolicy.NonShared,这样将有两个不同的对象导入到ClassA和ClassB [Export] [PartCreationPolicy(CreationPolicy.NonShared)] public class Part { public int Id { get; set; } } [Export] public class ClassA { [Impo

最近,我在WPF应用程序中使用MEF时遇到了一个问题。我创建了几个类,如下所示<代码>部分类型设置为
CreationPolicy.NonShared
,这样将有两个不同的对象导入到ClassA和ClassB

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class Part
{
    public int Id { get; set; }
}

[Export]
public class ClassA
{
    [Import]
    public Part PartA { get; set; }
}

[Export]
public class ClassB
{
    [Import]
    public Part PartB { get; set; }
}
我在下面写了一段代码来描述我的问题

[Export]
class Program
{
    [Import]
    public ClassA A { get; set; }

    [Import]
    public ClassB B { get; set; }

    [ImportMany(AllowRecomposition = true)]
    public IEnumerable<Part> AllParts { get; set; }

    static void Main(string[] args)
    {
        var catalog = new AssemblyCatalog(typeof(Program).Assembly);
        var container = new CompositionContainer(catalog);

        var prog = container.GetExportedValue<Program>();

        foreach (var part in prog.AllParts)
        {
            // Do something for Part instances.
            // I want to get all Part instances created by MEF which have imported to ClassA and ClassB.
            // However, it comes a list with a brand new Part instance.
        }
    }
}
[导出]
班级计划
{
[进口]
公共类A{get;set;}
[进口]
公共类B{get;set;}
[进口数量(AllowRecomposition=true)]
公共IEnumerable所有部分{get;set;}
静态void Main(字符串[]参数)
{
var catalog=新的AssemblyCatalog(typeof(Program).Assembly);
var容器=新的合成容器(目录);
var prog=container.GetExportedValue();
foreach(项目所有部分中的变量部分)
{
//为零件实例执行某些操作。
//我想得到所有由MEF创建的零件实例,它们已经导入到ClassA和ClassB。
//但是,它是一个带有全新零件实例的列表。
}
}
}
因此,将有ClassA、ClassB和导入程序对象的零件清单。事实上,我想要得到的是MEF容器创建的所有零件。但是,它是一个带有全新零件实例的列表

我理解这可能是因为
CreationPolicy.NonShared
我指定给
Part
类。但即使我试图在
container.Catalog.Parts
中找到它们,我也只在其中找到了一个
Part
实例。这让我很困惑。根据我的理解,容器应该包含它创建的对象的所有引用,因为我已经指定了
AllowRecomposition=true
。我找到了一个证据来证明这一点。它说:

容器和零件参考 我们相信.Net垃圾收集器是实现这一目标的最佳工具 适当的清理。但是,我们还需要提供一个具有确定性行为的容器。因此,除非满足以下条件之一,否则容器不会保存对其创建的零件的引用:

  • 该零件被标记为共享
  • 该部件实现IDisposable
  • 一个或多个导入配置为允许重新编译
对于这些情况,保留零件参考。再加上您可以拥有非共享部件并不断从容器中请求这些部件,那么内存需求很快就会成为一个问题。为了缓解这个问题,您应该依赖下面两个主题中讨论的以下策略之一

所以我有两个问题:

  • 为什么在容器中找不到多个
    Part
    type实例

  • 如何在演示中获取所有导出的
    零件
    实例


  • ImportMany
    不会做你认为它会做的事

    考虑以下几点:

    public interface IMyInterface
    {
        int Id { get; }
    }
    
    [Export(typeof(IMyInterface))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class Part1 : IMyInterface
    {
        public int Id { get; private set; }
    }
    
    [Export(typeof(IMyInterface))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class Part2 : IMyInterface
    {
        public int Id { get; private set; }
    }
    
    [Export]
    public class ClassA
    {
        [ImportMany]
        public IEnumerable<IMyInterface> Parts { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var catalog = new AssemblyCatalog(typeof(Program).Assembly);
            var container = new CompositionContainer(catalog);
    
            var a = container.GetExportedValue<ClassA>();
            // ...
        }
    }
    
    公共接口IMyInterface
    {
    int Id{get;}
    }
    [导出(类型(IMyInterface))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    公共类第1部分:IMyInterface
    {
    public int Id{get;private set;}
    }
    [导出(类型(IMyInterface))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    公共类第2部分:IMyInterface
    {
    public int Id{get;private set;}
    }
    [出口]
    甲级公共课
    {
    [进口数量]
    公共IEnumerable部分{get;set;}
    }
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    var catalog=新的AssemblyCatalog(typeof(Program).Assembly);
    var容器=新的合成容器(目录);
    var a=container.GetExportedValue();
    // ...
    }
    }
    
    此时,
    a.Parts
    属性将包含两个实例:一个
    Part1
    和一个
    Part2

    因此,
    ImportMany
    的目的不是获取以前导出的所有实例,而是获取导出接口的每个导出的新实例


    至于您提出的如何获取所有导出的非共享实例的问题,我认为这是不可能的,因为这就是非共享的关键所在

    谢谢您的回答。从你所说的,你的意思是MEF在这一点上只是一个工厂吗?我认为MEF作为一个容器,应该以某种方式保存引用。请注意我问题中的报价。它还说,即使在某些情况下没有共享导出,容器也会保存引用。您的代码有利于对象创建。然而,我实际上想做的是将所有非共享的文件导出到一个地方,以便在一个地方执行一些常见的操作。关于问题中的引用,在内部保留引用并不一定意味着有办法将它们放入列表中。也许它们只能用于重新编译。@Lucax我理解你的问题,正如我在回答中所说的,我认为这是不可能的。(即使是这样,也肯定不是用
    ImportMany
    完成的)也许如果您向我们提供更多关于您到底想要实现什么(即为什么需要这些实例)的详细信息,我们可以给您一个更好的建议。谢谢,Venemo。在您的帮助下,我发现不可能对非共享实例执行此操作。最后,我更改了我的设置,将它们设置为共享。