C# 如何处理MEF中的递归组合?
考虑下面的代码示例,该示例使用MEF创建类型为C# 如何处理MEF中的递归组合?,c#,recursion,mef,C#,Recursion,Mef,考虑下面的代码示例,该示例使用MEF创建类型为导入器的对象,导入类型为导入导出器的对象,然后导入类型为导出器,即导入器->导入导出器-/code>。该目录由一个合成实用程序管理(本例明显简化) 我知道MEF将在导入的零件上递归地解析导入。但是,因为我希望能够独立地实例化这些类中的每个类,所以每个具有导入的类也会在其构造函数中组合自己来解析这些导入 using System; using System.ComponentModel.Composition; using System.Compone
导入器
的对象,导入类型为导入导出器
的对象,然后导入类型为导出器
,即导入器->导入导出器-/code>。该目录由一个合成实用程序管理(本例明显简化)
我知道MEF将在导入的零件上递归地解析导入。但是,因为我希望能够独立地实例化这些类中的每个类,所以每个具有导入的类也会在其构造函数中组合自己来解析这些导入
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
namespace MefRecursionSample
{
class Program
{
static void Main(string[] args)
{
// var importerExporter = new ImporterExporter(); // include this and composition will work
var importer = new Importer();
Console.Write(importer.ImporterExporter.Exporter.Value); // should print 7
Console.ReadKey();
}
}
class CompositionUtility
{
static CompositionUtility()
{
var executingAssembly = Assembly.GetExecutingAssembly();
var assemblyCatalog = new AssemblyCatalog(executingAssembly);
_compositionContainer = new CompositionContainer(assemblyCatalog);
}
private static CompositionContainer _compositionContainer;
private static bool _isComposing;
public static void Compose(object part)
{
_compositionContainer.ComposeParts(part);
}
}
class Importer
{
public Importer()
{
CompositionUtility.Compose(this);
}
[Import]
public ImporterExporter ImporterExporter { get; set; }
}
[Export]
class ImporterExporter
{
public ImporterExporter()
{
CompositionUtility.Compose(this);
}
[Import]
public Exporter Exporter { get; set; }
}
[Export]
class Exporter
{
public int Value { get { return 7; } }
}
}
按原样运行代码会导致一个组合错误“MefRecursionSample.Importer类型的ComposablePart无法重新组合…”,这显然是因为我试图明确地组合MEF也想组合的东西
令我惊讶的是,当我包含Main
方法的第一行时,即在没有MEF的情况下创建类型为ImporterExporter
的对象,这种“双重组合”不再引起异常。为什么呢
此外,我如何使其工作,以便我能够独立地实例化其中的每一个,同时也使它们在像示例中那样链接时自行组合。我想我应该在CompositionUtility
上引入一个布尔标志\u compositionprogress
,并在设置该标志以避免递归合成时立即从Compose()
返回。有更好的方法吗?为什么不干脆这样做呢
class Program
{
private static CompositionContainer _compositionContainer;
static void Main(string[] args)
{
//compose the container just one time in your app
var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
_compositionContainer = new CompositionContainer(assemblyCatalog);
var importer = _compositionContainer.GetExportedValue<Importer>();
Console.Write(importer.ImporterExporter.Exporter.Value); // should print 7
Console.ReadKey();
}
}
[Export]
class Importer
{
[ImportingConstructor]
public Importer(ImporterExporter imex)
{
this.ImporterExporter = imex;
}
public ImporterExporter ImporterExporter { get; private set; }
}
[Export]
class ImporterExporter
{
[ImportingConstructor]
public ImporterExporter(Exporter exporter)
{
this.Exporter = exporter;
}
public Exporter Exporter { get; private set; }
}
[Export]
class Exporter
{
public int Value { get { return 7; } }
}
类程序
{
私有静态CompositionContainer\u CompositionContainer;
静态void Main(字符串[]参数)
{
//在应用程序中只编写一次容器
var assemblyCatalog=新的assemblyCatalog(Assembly.getExecutionGassembly());
_compositionContainer=新的compositionContainer(assemblyCatalog);
var importer=_compositionContainer.GetExportedValue();
Console.Write(importer.ImporterExporter.Exporter.Value);//应打印7
Console.ReadKey();
}
}
[出口]
类进口商
{
[导入构造函数]
公共进口商(进出口商imex)
{
this.ImporterExporter=imex;
}
公共导入导出器导入导出器{get;private set;}
}
[出口]
类导入导出器
{
[导入构造函数]
公共进出口商(出口商)
{
这个。出口商=出口商;
}
公共导出器{get;private set;}
}
[出口]
类出口商
{
公共int值{get{return 7;}}
}
为什么不干脆这样做呢
class Program
{
private static CompositionContainer _compositionContainer;
static void Main(string[] args)
{
//compose the container just one time in your app
var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
_compositionContainer = new CompositionContainer(assemblyCatalog);
var importer = _compositionContainer.GetExportedValue<Importer>();
Console.Write(importer.ImporterExporter.Exporter.Value); // should print 7
Console.ReadKey();
}
}
[Export]
class Importer
{
[ImportingConstructor]
public Importer(ImporterExporter imex)
{
this.ImporterExporter = imex;
}
public ImporterExporter ImporterExporter { get; private set; }
}
[Export]
class ImporterExporter
{
[ImportingConstructor]
public ImporterExporter(Exporter exporter)
{
this.Exporter = exporter;
}
public Exporter Exporter { get; private set; }
}
[Export]
class Exporter
{
public int Value { get { return 7; } }
}
类程序
{
私有静态CompositionContainer\u CompositionContainer;
静态void Main(字符串[]参数)
{
//在应用程序中只编写一次容器
var assemblyCatalog=新的assemblyCatalog(Assembly.getExecutionGassembly());
_compositionContainer=新的compositionContainer(assemblyCatalog);
var importer=_compositionContainer.GetExportedValue();
Console.Write(importer.ImporterExporter.Exporter.Value);//应打印7
Console.ReadKey();
}
}
[出口]
类进口商
{
[导入构造函数]
公共进口商(进出口商imex)
{
this.ImporterExporter=imex;
}
公共导入导出器导入导出器{get;private set;}
}
[出口]
类导入导出器
{
[导入构造函数]
公共进出口商(出口商)
{
这个。出口商=出口商;
}
公共导出器{get;private set;}
}
[出口]
类出口商
{
公共int值{get{return 7;}}
}
我考虑在合成实用程序
的合成
方法中设置的标志不起作用,因为可能会出现自动导入字符串中断的情况。例如,在问题的示例中,如果Exporter
使用new
在其构造函数中实例化了一个类,则该类将希望自行组合。在原始解决方案中,该类对Ccompose
的调用将立即返回,使该类保持未关闭状态
因为我想让类自行组合(因此用户甚至不必知道MEF),所以唯一的解决方案是建立规则,即具有[Export]
属性的类不能调用组合(this)
。因为它们在导入时将由MEF自动合成,这将导致“双重合成”,从而引发异常
如果要求标记为[Export]
的类必须通过new
独立实例化,而不是仅通过MEF导入,则它们必须具有一个带有布尔标志的附加构造函数,当设置好该标志时,会触发该类的合成。但是,默认行为必须是无组合,以避免上述“双重组合”。我考虑在组合实用程序的组合
方法中设置的标志不起作用,因为可能存在自动导入字符串中断的情况。例如,在问题的示例中,如果Exporter
使用new
在其构造函数中实例化了一个类,则该类将希望自行组合。在原始解决方案中,该类对Ccompose
的调用将立即返回,使该类保持未关闭状态
因为我想让类自行组合(因此用户甚至不必知道MEF),所以唯一的解决方案是建立规则,即具有[Export]
属性的类不能调用组合(this)
。因为它们在导入时将由MEF自动合成,这将导致“双重合成”,从而引发异常
如果要求标记有[Export]
的类