[英]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.