簡體   English   中英

使用Simple Injector在運行時注入數據解析的模型

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM