Работа с циклами сообщений в MVVM Light

#c# #mvvm-light

#c# #mvvm-light

Вопрос:

В моем приложении есть несколько объектов, которые одновременно отправляют и получают одно и то же сообщение. Например: порядок столбцов в таблице может быть изменен, когда пользователь перетаскивает столбцы в сетке, когда пользователь использует диалоговое окно настроек сетки и когда пользователь загружает другой отчет. Таким образом, сетка может как отправлять сообщение «Порядок столбцов изменен», так и получать сообщение.

Есть ли способ предотвратить получение сеткой своих собственных сообщений обратно? Поэтому, когда пользователь перетаскивает столбец, сетка отправляет сообщение «Порядок столбцов изменен» всем заинтересованным слушателям, но я не хочу, чтобы сетка затем перезванивала по своей подписке. Я мог бы использовать предикат и встроить некоторую информацию об отправителе в сообщение, но мне интересно, сможет ли Mvvm Light сам справиться с этим сценарием.

Ответ №1:

Проверьте эту перегрузку метода регистра IMessenger:

 /// <summary>
/// Registers a recipient for a type of message TMessage.
///             The action parameter will be executed when a corresponding
///             message is sent. See the receiveDerivedMessagesToo parameter
///             for details on how messages deriving from TMessage (or, if TMessage is an interface,
///             messages implementing TMessage) can be received too.
/// 
/// <para>
/// Registering a recipient does not create a hard reference to it,
///             so if this recipient is deleted, no memory leak is caused.
/// </para>
/// 
/// </summary>
/// <typeparam name="TMessage">The type of message that the recipient registers
///             for.</typeparam><param name="recipient">The recipient that will receive
///             the messages.</param><param name="token">A token for a messaging
///             channel. If a recipient registers using a token, and a sender sends
///             a message using the same token, then this message will be delivered to
///             the recipient. Other recipients who did not use a token when
///             registering (or who used a different token) will not get the message.
///             Similarly, messages sent without any token, or with a different
///             token, will not be delivered to that recipient.</param><param name="receiveDerivedMessagesToo">If true, message types deriving from
///             TMessage will also be transmitted to the recipient. For example, if a SendOrderMessage
///             and an ExecuteOrderMessage derive from OrderMessage, registering for OrderMessage
///             and setting receiveDerivedMessagesToo to true will send SendOrderMessage
///             and ExecuteOrderMessage to the recipient that registered.
/// 
/// <para>
/// Also, if TMessage is an interface, message types implementing TMessage will also be
///             transmitted to the recipient. For example, if a SendOrderMessage
///             and an ExecuteOrderMessage implement IOrderMessage, registering for IOrderMessage
///             and setting receiveDerivedMessagesToo to true will send SendOrderMessage
///             and ExecuteOrderMessage to the recipient that registered.
/// </para>
/// </param><param name="action">The action that will be executed when a message
///             of type TMessage is sent.</param>
void Register<TMessage>(object recipient, object token, bool receiveDerivedMessagesToo, Action<TMessage> action);
 

Примечание:

Токен для канала обмена сообщениями. Если получатель регистрируется с использованием токена, а отправитель отправляет сообщение с использованием того же токена, то это сообщение будет доставлено получателю. Другие получатели, которые не использовали токен при регистрации (или которые использовали другой токен), не получат сообщение. Аналогично, сообщения, отправленные без какого-либо токена или с другим токеном, не будут доставлены этому получателю.

Что вы можете сделать, так это зарегистрировать другие регистры этого сообщения с помощью токена, а затем, когда сетка отправляет сообщение, отправить с этим токеном. регистрация сетки не должна включать токен.

Комментарии:

1. Да, я это видел. Но проблема с использованием токенов для этого заключается в том, что каждому издателю потребуется свой собственный токен, и каждый подписчик должен будет подписаться на каждый токен, отличный от его собственного. Это становится довольно запутанным и сложным в обслуживании, чем больше издателей вы добавляете в систему. В моем случае у меня есть 3 объекта, которые могут как отправлять, так и получать, и четвертый, который просто получает. Я мог бы использовать Mvvm Light, чтобы при отправке сообщения вы могли передать объект, и если он совпадает с объектом получателя, который использовался при регистрации, тогда сообщение не доставляется.

2. @MattS Возможно, вашей сетке необходимо опубликовать сообщения другого типа, на которые она не подписывается. Должна быть разница, поскольку сообщения должны обрабатываться по-разному.

3. Тогда у каждого издателя будет свой вариант одного и того же сообщения, и всем им нужно будет подписаться на разные варианты.

4. @MattS Как насчет того, чтобы перехватить перемещение столбца сетки и т. д. Отменить его, но все равно отправить сообщение. Затем попросите обработчик выполнить перемещение, точно так же, как это было бы из любого другого места.

5. как насчет добавления GetHashCode() в качестве идентификатора к сообщению. Если это ваш идентификатор, игнорируйте его. Или добавьте экземпляр к вашему объекту в сообщении (например, object Sender { get; set; }, если вы его игнорируете.