// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; // This file has two types which implement interfaces that can be projected to WInRT, ie. // 'Observable.Recipient' and 'Observable.Recipient', which // implement 'IDisposable' (which is projected to 'IClosable'). These types are not meant // to be used in interop scenarios (including in eg. bindings), as they're only meant to // be used by code behind interacting with System.Reactive APIs. As such, we skip marking // them partial, as we don't need CCW vtables to be generated for them. #pragma warning disable CsWinRT1028 namespace CommunityToolkit.Mvvm.Messaging; /// partial class IMessengerExtensions { /// /// Creates an instance that can be used to be notified whenever a message of a given type is broadcast by a messenger. /// /// The type of message to use to receive notification for through the resulting instance. /// The instance to use to register the recipient. /// An instance to receive notifications for messages being broadcast. /// Thrown if is . public static IObservable CreateObservable(this IMessenger messenger) where TMessage : class { ArgumentNullException.ThrowIfNull(messenger); return new Observable(messenger); } /// /// Creates an instance that can be used to be notified whenever a message of a given type is broadcast by a messenger. /// /// The type of message to use to receive notification for through the resulting instance. /// The type of token to identify what channel to use to receive messages. /// The instance to use to register the recipient. /// A token used to determine the receiving channel to use. /// An instance to receive notifications for messages being broadcast. /// Thrown if or are . public static IObservable CreateObservable(this IMessenger messenger, TToken token) where TMessage : class where TToken : IEquatable { ArgumentNullException.ThrowIfNull(messenger); ArgumentNullException.For.ThrowIfNull(token); return new Observable(messenger, token); } /// /// An implementations for a given message type. /// /// The type of messages to listen to. private sealed class Observable : IObservable where TMessage : class { /// /// The instance to use to register the recipient. /// private readonly IMessenger messenger; /// /// Creates a new instance with the given parameters. /// /// The instance to use to register the recipient. public Observable(IMessenger messenger) { this.messenger = messenger; } /// public IDisposable Subscribe(IObserver observer) { return new Recipient(this.messenger, observer); } /// /// An implementation for . /// private sealed class Recipient : IRecipient, IDisposable { /// /// The instance to use to register the recipient. /// private readonly IMessenger messenger; /// /// The target instance currently in use. /// private readonly IObserver observer; /// /// Creates a new instance with the specified parameters. /// /// The instance to use to register the recipient. /// The instance to use to create the recipient for. public Recipient(IMessenger messenger, IObserver observer) { this.messenger = messenger; this.observer = observer; messenger.Register(this); } /// public void Receive(TMessage message) { this.observer.OnNext(message); } /// public void Dispose() { this.messenger.Unregister(this); } } } /// /// An implementations for a given pair of message and token types. /// /// The type of messages to listen to. /// The type of token to identify what channel to use to receive messages. private sealed class Observable : IObservable where TMessage : class where TToken : IEquatable { /// /// The instance to use to register the recipient. /// private readonly IMessenger messenger; /// /// The token used to determine the receiving channel to use. /// private readonly TToken token; /// /// Creates a new instance with the given parameters. /// /// The instance to use to register the recipient. /// A token used to determine the receiving channel to use. public Observable(IMessenger messenger, TToken token) { this.messenger = messenger; this.token = token; } /// public IDisposable Subscribe(IObserver observer) { return new Recipient(this.messenger, observer, this.token); } /// /// An implementation for . /// private sealed class Recipient : IRecipient, IDisposable { /// /// The instance to use to register the recipient. /// private readonly IMessenger messenger; /// /// The target instance currently in use. /// private readonly IObserver observer; /// /// The token used to determine the receiving channel to use. /// private readonly TToken token; /// /// Creates a new instance with the specified parameters. /// /// The instance to use to register the recipient. /// The instance to use to create the recipient for. /// A token used to determine the receiving channel to use. public Recipient(IMessenger messenger, IObserver observer, TToken token) { this.messenger = messenger; this.observer = observer; this.token = token; messenger.Register(this, token); } /// public void Receive(TMessage message) { this.observer.OnNext(message); } /// public void Dispose() { this.messenger.Unregister(this, this.token); } } } }