最近,我在WPF应用程序中使用MEF时遇到了问题。我创建了几个类,如下所示。 Part
类型设置为CreationPolicy.NonShared
,因此将有2个不同的对象导入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.
}
}
}
因此会有ClassA,ClassB和导入到Program对象的Part intances列表。实际上,我想要得到的是MEF容器创建的所有Part部分。但是,它带有一个全新的Part实例列表。
我理解这可能是因为我CreationPolicy.NonShared
指定了Part
。但即使我尝试在container.Catalog.Parts
中找到它们,我也发现其中只有一个Part
个实例。这让我感到困惑。根据我的理解,容器应该包含它创建的对象的所有引用,因为我已经指定了AllowRecomposition = true
。我找到了article来证明这一点。它说:
容器和零件参考
我们相信.Net垃圾收集器是最好的依赖 适当的清理。但是,我们还需要提供具有确定性行为的容器。因此,除非满足下列条件之一,否则容器将不会保留对其创建的零件的引用:
- 该部件标记为共享
- 该部分实现IDisposable
- 配置一个或多个导入以允许重新组合
对于这些情况,保留零件参考。结合您可以拥有非共享部分并继续从容器中请求这些部分这一事实,内存需求可能很快成为问题。为了缓解此问题,您应该依赖以下两个主题中讨论的以下策略之一。
所以我有两个问题:
为什么我在容器中找不到多个Part
类型的实例?
如何在演示中获取所有导出的Part
个实例?
答案 0 :(得分:1)
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>();
// ...
}
}
此时,a.Parts
属性将包含两个实例:一个Part1
和一个Part2
。
因此,目的ImportMany
不是为了获取所有以前导出的实例,而是为了获取导出界面的每个导出的新实例。
关于如何获取所有导出的非共享实例的问题,我不相信这是可能的,因为这是非共享强>