【发布时间】:2013-09-06 23:06:27
【问题描述】:
我对 DI 很陌生,我有几个问题希望人们能帮我解决,我目前正在使用 MEF 容器开发一个使用 Caliburn Micro 的 WPF-MVVM 系统。
此应用程序用于跟踪货物,并包含几个部分。我希望我能解释得足够清楚,但如果不清楚,请指出。
我有几个从数据库(通过 Web 服务)返回的实体,例如 shipments、containers、packages。
对于这些实体中的每一个,我都有一个包装 web 服务实体的 model,以及一个 manager,manager 还负责通过 web 服务进行标准 CRUD 操作由于存储了 model 的 ObservableCollection,这些管理器随后被注入到需要访问这些列表的 viewmodels 的构造函数中。
所以,我有 shipment > shipmentManager > shipmentListViewModel,这样做是为了允许多个 viewmodels 使用相同的 出货量
但是,我开始遇到一些问题,即一些 viewmodels 的构造函数包含 6 个以上 managers,而有些情况仅用于传递给新构造的 dialog viewmodels。
我希望有人可以为这个问题提出一个干净的解决方案,我正在考虑一个单一的类,它将成为所有 经理的容器,并且然后我可以简单地注入那个 container 类并使用它来获得所需的 Manager,但是我看到有人建议反对这种方法,但没有明确说明原因。
还有一个问题,我的模型实现了IEditableObject,因为我的经理负责维护模型列表,以及保存对这些模型的更改,在EndEdit 内发布经理 选择的事件会是一个问题吗?
编辑:要求的代码:
引导程序创建并导出所需的类:
protected override void Configure()
{
container = new CompositionContainer(new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()));
CompositionBatch batch = new CompositionBatch();
IEventAggregator eventAggregator = new EventAggregator();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(eventAggregator);
batch.AddExportedValue<IManager<ShipmentContainer>>(new ContainerManager());
batch.AddExportedValue<IManager<Item>>(new ItemManager());
batch.AddExportedValue<IManager<OrderedItem>>(new OrderedItemManager());
batch.AddExportedValue<IManager<Package>>(new PackageManager());
batch.AddExportedValue<IManager<Proforma>>(new ProformaManager(eventAggregator));
batch.AddExportedValue<IManager<Project>>(new ProjectManager());
batch.AddExportedValue<IManager<Shipment>>(new ShipmentManager(eventAggregator));
batch.AddExportedValue<IManager<PackingItem>>(new PackingListManager(eventAggregator));
batch.AddExportedValue(container);
container.Compose(batch);
}
ContentViewModel 处理了菜单点击,允许打开几个diaglogs,构造函数包含大量DI:
public LBLContentViewModel(IWindowManager windowManager, IManager<Project> pManager, IEventAggregator eventManager, IManager<Item> iManager, IManager<PackingItem> plManager, IManager<Shipment> sManager)
{
...
}
对话框显示如下:
public void OpenProject()
{
ProjectSearchViewModel viewModel = new ProjectSearchViewModel(_eventAggregator, _projectManager);
this._windowManager.ShowDialog(viewModel);
}
希望这是你想见 charleh 的代码,如果不是,请告诉我,我会尽力提供所需的。
【问题讨论】:
-
好的 - 所以你需要得到一个
ProjectSearchViewModel的实例 - 为什么不直接使用IoC.Get<ProjectSearchViewModel>()(你的虚拟机也应该被导出) - 然后将你的IEventAggregator和IManager<Project>移动到ProjectSearchViewModel的构造函数。你在这里做的不是 IoC,因为依赖的控制在于一个臃肿的类 -
我认为这就是 margabit 的建议,我现在打算这样做,我有点担心引导程序中的导出数量,但我认为这不是问题?
-
很多 IoC 容器允许您根据约定批量注册依赖项 - 不确定 MEF 允许您做什么,但是显式地一一导出所有对象是正常的(批量注册是为了制作东西而发明的在这些注册课程中少一点罗嗦,仅此而已)
-
太好了,再次感谢您的帮助,charleh。我有点担心显示该代码,因为我觉得我做错了什么,谢天谢地似乎没有。
-
一个例子——在温莎你会使用
_container.Register(Classes.FromThisAssembly().InSameNamespaceAs<SomeClass>())而不是明确地注册所有东西。 MEF 似乎支持约定,但我必须阅读一下它到底支持什么
标签: c# wpf mvvm dependency-injection caliburn.micro