c# - 在 MVVM 中使用 MEF 创建 ViewModel
问题描述
这会有点长,所以请抓紧时间。
我有一个Caliburn.Micro
用于实现 MVVM 模式的项目。对于 IoC,我使用的是 MEF。所有的 ViewModel 都标有属性[Export(typeof(IScreen))]
。IScreen
中定义Caliburn.Micro
。
在我的BootStrapper
文件中,我像这样设置了 MEF:
private CompositionContainer container;
protected override void Configure()
{
//Set up MEF
container = new CompositionContainer(new AggregateCatalog``AssemblySource.Instance.Select``(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()));
var batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(container);
container.Compose(batch);
//Other stuff
}
现在,我展示了第一个 ViewModel 使用
protected override void OnStartup(object sender, StartupEventArgs e) => DisplayRootViewFor<ViewModels.Main.MainViewModel>();
这一切都很好,花花公子。现在,当我想从一个切换ViewModel
到另一个时,问题就开始了。
ViewModel 的一个示例是:
[PartCreationPolicy(CreationPolicy.NonShared), Export(typeof(IScreen))]
sealed class SampleViewModel: ScreenVMwithUoW<IAddItemUoW>
{
[ImportingConstructor]
public SampleViewModel(IAddItemUoW uow, IEventAggregator eventAggregator) : base(uow, eventAggregator)
{
}
//bla bla bla
}
假设我想打开SampleViewModel
和关闭我的MainViewModel
. 我如何使用 MEF 做到这一点?
这是我现在正在做的事情:
[Export(typeof(IScreenFactory))]
class ScreenFactory : IScreenFactory
{
private Dictionary<Type, ExportFactory<IScreen>> _screenDictionary { get; set; }
private IEnumerable<ExportFactory<IScreen>> _screenfactoryCollection { get; set; }
private ExportLifetimeContext<IScreen> _currentScreenLifeTimeCtx { get; set; }
[ImportingConstructor]
public ScreenFactory([ImportMany(AllowRecomposition = true)] IEnumerable<ExportFactory<IScreen>> screenList)
{
_screenfactoryCollection = screenList;
_reportfactoryCollection = reportsList;
}
public IScreen GetScreen(Type t)
{
if (_screenDictionary == null)
{
PopulateScreenDictionary(_screenfactoryCollection);
}
_currentScreenLifeTimeCtx = _screenDictionary[t].CreateExport();
return _currentScreenLifeTimeCtx.Value;
}
private void PopulateScreenDictionary(IEnumerable<ExportFactory<IScreen>> screenfactories)
{
_screenDictionary = screenfactories.ToDictionary(c => c.CreateExport().Value.GetType(), c => c);
}
public void DisposeCurrentScreenContext()
{
_currentScreenLifeTimeCtx?.Dispose();
}
public void Dispose()
{
DisposeCurrentScreenContext();
}
}
每当我需要 a 的新实例时ViewModel
,我都会这样做:
DeactivateItem(ActiveItem, true);
_vmFactory.DisposeCurrentScreenContext();
ActivateItem(_vmFactory.GetScreen(NextViewModelName));
这不能是这样做的正常方式。此外,这也增加了对性能的巨大冲击,尤其是应用程序的启动时间,当ViewModel
s 的数量增加到大约 25-30 时。
如果可能的话,我还想避免使用服务定位器模式。我也愿意使用适当的 IoC Container 而不是MEF
,但MEF
允许我轻松添加 ViewModels。只需添加注释即可[Export(typeof(IScreen))]
完成工作。
解决方案
推荐阅读
- string - Julia:是否可以通过将一段内存重新解释为字符串来创建字符串?
- java - 多个 sc.nextLine(); 一个接一个地运行,但需要运行 if/else 语句
- macros - 周围有 lisp 宏的麻烦和
- python - 寻找影响净收入的特征
- javascript - 如何对 axios 响应拦截器进行自定义错误代码检查?
- php - PHP CodeIgniter AJAX POST方法不起作用
- java - Sum pairs that are divisible
- django - 无法使用导航栏处理视图内的功能
- kotlin - 了解初始化为扩展函数的参数
- git - package.json 尚未准备好 node-pre-gyp,但这些属性是什么意思?