[英]Injecting data resolved models at runtime with Simple Injector
我正在WPF中使用Simple Injector构建应用程序,并且遇到了要在运行时解析模型以将其注入ViewModel的问题。 例如,假设我有一个窗口来编辑需要使用用户模型的ViewModel的用户。 从列表中选择该用户模型,然后将其注入到ViewModel的构造函数中。 如何使用Simple Injector将这些数据输入到ViewModel中? 那有可能吗? 我想是否有可能使用某种形式的工厂? 我一直在讨论将MVVM组件以外的所有组件都使用Simple Injector作为解决方法-除非我能找到一个好的解决方案。
如果我应该张贴一些示例代码或类似的内容以更明确地定义问题,请告诉我。 这是我第一次使用DI容器运行,并且我想了解如何用一个容器最好地设计我的应用程序。
使用首选的方法实际上是不可能的。 那是因为您的设计不是最佳的。 如您在此处所读,在应用程序的组件中注入运行时数据是一种反模式。
用于编辑用户的模型是运行时数据,因此应通过方法注入在您的应用程序中流动。
所以你可以这样解决:
public interface IViewModel<T>
{
void EditItem(T item);
}
class UserEditViewModel : IViewModel<User>
{
public void EditItem(User item)
{
// bind properties etc...
}
}
通常,您将IViewModel<User>
注入用户主视图模型中。
基于此而这个设计,你能想象一个更灵活的解决方案。 如果您看到在编辑用户时执行的命令只是触发并在完成时返回,则可以在链接的QueryProcessor
定义基础组件。 这将成为一个EditProcessor
,用于处理应用程序中的所有编辑操作。 一个实现非常简单,看起来像:
class EditProcessor : IEditProcessor
{
private readonly Container container;
public EditProcessor(Container container)
{
this.container = container;
}
public void EditItem<T>(T item)
{
var viewModel = typeof (IViewModel<>).MakeGenericType(typeof (T));
dynamic instance = container.GetInstance(viewModel);
instance.EditItem((dynamic) item);
}
}
现在您到处都需要编辑一些模型,只需注入IEditProcessor
并调用
this.editProcessor.EditItem(yourItem);
可以扩展EditProcessor
这种简单实现,将具有各种不错的功能,例如在编辑之前对项目进行备份,因此用户可以取消编辑表单。
如果您使用某些MVVM工具箱将视图绑定到视图模型,那么这也是将您的DI容器与MVVM工具箱彼此很好地交互的地方。
您不应该将模型注入到ViewModel中。
听起来更像您需要事件汇总器/ messanger。 您可以将事件聚合器注入到您的视图模型中,并订阅某个事件并将其从另一个ViewModel中引发。
public class CustomersViewModel
{
private readonly IEventAggregator eventAggregator;
public CustomersViewModel(IEventAggregator eventAggregator)
{
if(eventAggregator==null)
{
throw new ArgumentNullException("eventAggregator");
}
this.eventAggregator = eventAggregator;
}
private Customer selectedCustomer;
public Customer SelectedCustomer
{
get { return selectedCustomer; }
set
{
if(selectedCustomer!=value)
{
selectedCustomer = value;
eventAggregator.Publish(new CustomerSelectedEvent(selectedCustomer);
}
}
}
}
public class CustomerOrdersViewModel
{
private readonly IEventAggregator eventAggregator;
private readonly IOrderRepository orderRepository;
private ObservableCollection<Order> orders;
public ObservableCollection<Order> Orders {
get { return orders; }
set
{
if(orders != value)
{
orders = value;
OnPropertyChanged("Orders");
}
}
}
public CustomerDetailViewModel(IEventAggregator eventAggregator, IOrderRepository orderRepository)
{
if(eventAggregator==null)
{
throw new ArgumentNullException("eventAggregator");
}
this.eventAggregator = eventAggregator;
this.eventAggregator.Subscribe<CustomerSelectedEvent>(OnCustomerSelected);
...
}
private async void OnCustomerSelected(CustomerSelectedEvent event)
{
Orders = new ObservableCollection<Order>(await orderRepository.GetOrdersByCustomer(event.Customer.Id);
}
}
其中SelectedCustomerEvent
是简单的POCO类。
public class SelectedCustomerEvent
{
public Customer Customer { get; }
public SelectedCustomerEvent(Customer customer)
{
// C# 6.0, otherwise add a private setter
Customer = customer;
}
}
事件聚合器的实现有点超出范围,但是有些消息传递/事件聚合器附带的框架(例如,Prism PubSubEvents)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.