简体   繁体   English

MVVMLight :这是使用 Messenger 的正确方法吗?

[英]MVVMLight : is this the right way to use the Messenger?

I have a classic business application that manages clients and adresses.我有一个管理客户和地址的经典业务应用程序。

There are tab items (Id, GenericInfo and a few more) with each their own ViewModel.有选项卡项(Id、GenericInfo 等),每个项都有自己的 ViewModel。

There is a MainViewModel that handles the save and load commands of a client and its addresses.有一个 MainViewModel 处理客户端及其地址的保存和加载命令。

We retrieve the data from a WCF service.我们从 WCF 服务中检索数据。 The data received/sent from each WCF Function is aggregated in a different container.从每个 WCF 函数接收/发送的数据聚合在不同的容器中。


In my MainViewModel I create a SaveContainer and then send it with the messenger.在我的 MainViewModel 中,我创建了一个 SaveContainer,然后将它与 Messenger 一起发送。

    public void Save()
    {
        var container = new SaveContainer();

        MessengerInstance.Send(container);

        //the container is now populated and ready to be sent via WCF

        Console.WriteLine(container.User.Name);
        Console.WriteLine(container.Address.StreetName);
        Console.WriteLine(container.Address2.StreetName);
    }

In my UserViewModel is register for that container and then the viewmodel populate it with the data it has (the user).在我的 UserViewModel 中注册了该容器,然后视图模型用它拥有的数据(用户)填充它。

    public UserViewModel()
        : base(Messenger.Default)
    {
        User = new User();

        MessengerInstance.Register<SaveContainer>(this, (x) => x.User = User);
    }

And in my AddressViewModel I do the same.在我的 AddressViewModel 中,我也这样做。

    public AddressViewModel()
        : base(Messenger.Default)
    {
        Address = new Address();
        Address2 = new Address() { StreetName = "Washington Street" };

        MessengerInstance.Register<SaveContainer>(this, x =>
        {
            x.Address = Address;
            x.Address2 = Address2;
        });
    }

I'd do the same when I have to load data.当我必须加载数据时,我也会这样做。


After I send the Message, I assume that every ViewModel registered received the message and handled it.在我发送消息后,我假设每个注册的 ViewModel 都收到了消息并处理了它。 Am I assuming wrong?我假设错了吗? Do you find this way a correct way to use the Messenger?您认为这种方式是使用 Messenger 的正确方式吗? What would you improve?你会改进什么?

There is no right way to use the messenger.没有使用信使的正确方法。 However, you will have to consider that the message is handled by all recipients that have registerd for the message, not just an intended subset.但是,您必须考虑到该消息由所有注册该消息的收件人处理,而不仅仅是预期的子集。 Furthermore, when using messaging you do not have control over when the message handling is finished, now do you get notified when all recipients are done handling the message.此外,在使用消息传递时,您无法控制消息处理何时完成,现在您是否会在所有收件人处理完消息时收到通知。 In addition - depending on the implementation of the messenger - the messages may be handled in parallel.此外 - 取决于信使的实现 - 可以并行处理消息。

So the problem with your approach (and @cadrell0's extension using a callback) is that you don't know when all recipients have handled the message.因此,您的方法(以及@cadrell0 使用回调的扩展名)的问题在于您不知道所有收件人何时都处理了消息。 Using the callback you will get a callback for each recipient handling the message (ie n recipients n callbacks).使用回调,您将获得处理消息的每个接收者的回调(即 n 个接收者 n 个回调)。

So how can you check when all recipients are done handling the message?那么如何检查所有收件人何时处理完邮件?

  • You use a counter to determine how many recipients have called back - this is error prone as you might register another message recipient and this messes up your system.您使用计数器来确定有多少收件人已回电 - 这很容易出错,因为您可能会注册另一个邮件收件人,这会弄乱您的系统。
  • Another way would be validating the save container and once it is complete continue processing - but this might lead to a race condition as you may think all recipients have handled the message and continue, but then one late recipient calls in and invalidates your save container ... not good.另一种方法是验证保存容器并在它完成后继续处理 - 但这可能会导致竞争条件,因为您可能认为所有收件人都已处理消息并继续,但后来一个迟到的收件人调用并使您的保存容器无效。 .. 不好。

As I see it the messaging is more designed as a notification mechanism, ie you notify some recipients that something has happened.在我看来,消息传递更像是一种通知机制,即您通知某些收件人发生了某些事情。 If you know and can ensure that there is only one recipient you even can use it in a manner you describe, but as soon as more than one recipient is involved this causes the mentioned problems.如果您知道并且可以确保只有一个收件人,您甚至可以按照您描述的方式使用它,但是一旦涉及多个收件人,就会导致上述问题。

So where does this leave you ... in your szenario I would tend to design the viewmodels as "related" (ie the main view model knows about the user view model and the address view models - or the main view model knows about the user view model that in turn knows about the address view models if that is more appropriate).那么这会让你在哪里......在你的szenario中我倾向于将视图模型设计为“相关”(即主视图模型知道用户视图模型地址视图模型 - 或者主视图模型知道用户如果更合适的话,视图模型又知道地址视图模型)。 Usually, I also would desing a model that holds the unit of work that I have to deal with (in your case the SaveContainer).通常,我还会设计一个模型来保存我必须处理的工作单元(在您的情况下是 SaveContainer)。 Then all view models are constructed from this model and write their data to it.然后所有的视图模型都是从这个模型构建的,并将它们的数据写入其中。 In normal cases this unit of work is what you get from your data storage service and what, in turn, gets saved by the data store in a single transaction.在正常情况下,此工作单元是您从数据存储服务中获得的内容,而数据存储又会在单个事务中保存这些内容。

But again, there is no right way to MVVM!但同样,MVVM 没有正确的方法!

If I need to do something after a recipient responds to a message I include a callback on my message.如果我需要在收件人回复消息后做某事,我会在我的消息中包含回调。 When the recipient is done, it executes the callback.当接收者完成时,它执行回调。 Adding parameters to the callback allows the recipient to send data to the sender.向回调添加参数允许接收者向发送者发送数据。 This also allows the recipient to perform an async operation.这也允许接收者执行异步操作。

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

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