我正在尝试用MEF编写一个小模块系统,所以我有一个像这样的基本模块:
public abstract class Module : IModule
{
[Import]
private IShell _shell;
protected IShell Shell
{
get { return _shell; }
}
}
还有一些模块如下:
[Export(typeof(IModule))]
public class TodoListModule : Module
{
}
如您所见,基本模块依赖于IShell。我有一个实现,像这样:
[Export(typeof(IShell))]
public class ShellViewModel : IShell
{
[ImportMany]
private IEnumerable<IModule> _modules;
.... and later...
private void InitializeModules()
{
foreach (var module in _modules)
{
// init modules.
}
}
}
所以shell负责加载模块。
问题是当我有多个模块实现时,我得到了这个例外:
GetExportedValue cannot be called before prerequisite import '...ShellViewModel..ctor' has been set.
因此,原因是我们有2个实现通过基类获得IShell
。为什么会这样?
这是我的容器配置:
// Add all assemblies to AssemblySource (using a temporary DirectoryCatalog).
var directoryCatalog = new DirectoryCatalog(@"./");
AssemblySource.Instance.AddRange(
directoryCatalog.Parts
.Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly)
.Where(assembly => !AssemblySource.Instance.Contains(assembly)));
// Prioritise the executable assembly. This allows the client project to override exports, including IShell.
// The client project can override SelectAssemblies to choose which assemblies are prioritised.
var priorityAssemblies = SelectAssemblies().ToList();
var priorityCatalog = new AggregateCatalog(priorityAssemblies.Select(x => new AssemblyCatalog(x)));
var priorityProvider = new CatalogExportProvider(priorityCatalog);
// Now get all other assemblies (excluding the priority assemblies).
var mainCatalog = new AggregateCatalog(
AssemblySource.Instance
.Where(assembly => !priorityAssemblies.Contains(assembly))
.Select(x => new AssemblyCatalog(x)));
var mainProvider = new CatalogExportProvider(mainCatalog);
container = new CompositionContainer(priorityProvider, mainProvider);
priorityProvider.SourceProvider = container;
mainProvider.SourceProvider = container;
var batch = new CompositionBatch();
BindServices(batch);
batch.AddExportedValue(mainCatalog);
container.Compose(batch);
当任何其他类导入IShell