简体   繁体   English

使用Simple Injector在运行时注入数据解析的模型

[英]Injecting data resolved models at runtime with Simple Injector

I am building an app with Simple Injector in WPF and I have run into the issue where I want to resolve my Models to inject into my ViewModels at runtime. 我正在WPF中使用Simple Injector构建应用程序,并且遇到了要在运行时解析模型以将其注入ViewModel的问题。 For instance, say I have a window to edit users that requires a ViewModel with a User Model. 例如,假设我有一个窗口来编辑需要使用用户模型的ViewModel的用户。 This user model is selected from a list and then injected into the ViewModel's constructor. 从列表中选择该用户模型,然后将其注入到ViewModel的构造函数中。 How would I get this data into the ViewModel with Simple Injector? 如何使用Simple Injector将这些数据输入到ViewModel中? Is that even possible? 那有可能吗? I figure if it is possible I would use some form of factory maybe? 我想是否有可能使用某种形式的工厂? I was debating on using Simple Injector for everything except my MVVM components as a workaround--that is unless I can find a good solution. 我一直在讨论将MVVM组件以外的所有组件都使用Simple Injector作为解决方法-除非我能找到一个好的解决方案。

If I should post some example code or anything like that to give a more clear definition of the problem, let me know. 如果我应该张贴一些示例代码或类似的内容以更明确地定义问题,请告诉我。 This is my first run with a DI Container and I want to understand how to best design my application with one. 这是我第一次使用DI容器运行,并且我想了解如何用一个容器最好地设计我的应用程序。

Using the prefered approach what you're aiming for is indeed not possible. 使用首选的方法实际上是不可能的。 That is because your design is not optimal. 那是因为您的设计不是最佳的。 As you can read here injecting runtime data in the components of your application is an anti-pattern. 如您在此处所读,在应用程序的组件中注入运行时数据是一种反模式。

The model for editing your users is runtime data and should thus flow through your application via method injection. 用于编辑用户的模型是运行时数据,因此应通过方法注入在您的应用程序中流动。

So you could solve this like: 所以你可以这样解决:

public interface IViewModel<T>
{
    void EditItem(T item);
}

class UserEditViewModel : IViewModel<User>
{
    public void EditItem(User item)
    {
        // bind properties etc...
    }
}

You would typically inject the IViewModel<User> in your user master viewmodel. 通常,您将IViewModel<User>注入用户主视图模型中。

Based on this and this design you can imagine a far more flexible solution. 基于这个设计,你能想象一个更灵活的解决方案。 If you would see editing a user as performing a command which you just fire and returns when it's finished, you could define a infrastructal component a la the QueryProcessor from the link. 如果您看到在编辑用户时执行的命令只是触发并在完成时返回,则可以在链接的QueryProcessor定义基础组件。 This would become an EditProcessor which handles all your edit operations in your application. 这将成为一个EditProcessor ,用于处理应用程序中的所有编辑操作。 An implementation is pretty simple and would look something like: 一个实现非常简单,看起来像:

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);
    }
}

Now everywhere you need to edit some model, you only inject IEditProcessor and call 现在您到处都需要编辑一些模型,只需注入IEditProcessor并调用

this.editProcessor.EditItem(yourItem);

This simple implementation of an EditProcessor can be extended will all kinds of nice features like making a backup of the item before editing, so the user could cancel the editform for example. 可以扩展EditProcessor这种简单实现,将具有各种不错的功能,例如在编辑之前对项目进行备份,因此用户可以取消编辑表单。

If you use some MVVM toolkit to bind your view to your viewmodel this would also be the place to bring your DI container and the MVVM toolkit interact with eachother nicely. 如果您使用某些MVVM工具箱将视图绑定到视图模型,那么这也是将您的DI容器与MVVM工具箱彼此很好地交互的地方。

You shouldn't inject models into your ViewModel. 您不应该将模型注入到ViewModel中。

Sounds more like you need an event aggregator/messanger. 听起来更像您需要事件汇总器/ messanger。 You would inject the event aggregator into your view models and subscribe to a certain event and rise it form another ViewModel. 您可以将事件聚合器注入到您的视图模型中,并订阅某个事件并将其从另一个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);
    }
}

Where the SelectedCustomerEvent would be a simple POCO class. 其中SelectedCustomerEvent是简单的POCO类。

public class SelectedCustomerEvent 
{
    public Customer Customer { get; }

    public SelectedCustomerEvent(Customer customer) 
    {
        // C# 6.0, otherwise add a private setter
        Customer = customer;
    }
}

The implementation of the event aggregator is a bit out of the scope, but there are frameworks that come with messanger/event aggregators (Prism PubSubEvents for example). 事件聚合器的实现有点超出范围,但是有些消息传递/事件聚合器附带的框架(例如,Prism PubSubEvents)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM