繁体   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