Aracılığıyla paylaş


Messenger

IMessenger Arabirim, farklı nesneler arasında ileti alışverişi yapmak için kullanılabilecek türler için bir sözleşmedir. Bu, başvurulmakta olan türlere güçlü başvurular sağlamak zorunda kalmadan bir uygulamanın farklı modüllerini ayırmada yararlı olabilir. Belirli kanallara belirteçle benzersiz olarak tanımlanan iletiler göndermek ve uygulamanın farklı bölümlerinde farklı messenger'lara sahip olmak da mümkündür. MVVM Araç Seti, kutusundan iki uygulama sağlar: WeakReferenceMessenger ve StrongReferenceMessenger: birincisi, alıcılara otomatik bellek yönetimi sunan zayıf başvuruları dahili olarak kullanır, ikincisi ise güçlü başvurular kullanır ve geliştiricilerin artık gerekli olmadığında alıcılarının aboneliklerini el ile kaldırmasını gerektirir (ileti işleyicilerinin kaydını kaldırma hakkında daha fazla ayrıntı aşağıda bulunabilir), ancak bunun karşılığında daha iyi performans ve çok daha az bellek kullanımı sunar.

Platform API'leri:IMessenger, WeakReferenceMessenger, StrongReferenceMessenger, IRecipient<TMessage>, MessageHandler<TRecipient, TMessage>, ObservableRecipient, AsyncRequestMessage<T>RequestMessage<T>CollectionRequestMessage<T>AsyncCollectionRequestMessage<T>, .

Nasıl çalışır?

Uygulayan IMessenger türler, göreli ileti işleyicileri ile alıcılar (iletilerin alıcıları) ve kayıtlı ileti türleri arasındaki bağlantıları korumakla sorumludur. Herhangi bir nesne, bir ileti işleyicisi kullanılarak belirli bir ileti türü için alıcı olarak kaydedilebilir. Bu, örnek bu türde bir ileti göndermek için her IMessenger kullanıldığında çağrılır. Birden çok modülün çakışmaya neden olmadan aynı türdeki iletileri değiş tokuş edebilmesi için belirli iletişim kanalları aracılığıyla (her biri benzersiz bir belirteçle tanımlanan) ileti göndermek de mümkündür. Belirteç olmadan gönderilen iletiler varsayılan paylaşılan kanalı kullanır.

İleti kaydını gerçekleştirmenin IRecipient<TMessage> iki yolu vardır: arabirim aracılığıyla veya ileti işleyicisi olarak davranan bir MessageHandler<TRecipient, TMessage> temsilciyi kullanma. birincisi, tüm işleyicileri uzantıya RegisterAll tek bir çağrıyla kaydetmenize olanak tanır ve bu da bildirilen tüm ileti işleyicilerinin alıcılarını otomatik olarak kaydederken, ikincisi daha fazla esnekliğe ihtiyacınız olduğunda veya basit bir lambda ifadesini ileti işleyicisi olarak kullanmak istediğinizde kullanışlıdır.

StrongReferenceMessenger Hem hem de WeakReferenceMessenger pakette yerleşik olarak iş parçacığı güvenli bir uygulama sunan bir özelliği kullanıma sunarDefault. Gerekirse, örneğin uygulamanın farklı bir modülüne (örneğin, aynı işlemde çalışan birden çok pencere) farklı bir DI hizmet sağlayıcısı eklendiğinde birden çok messenger örneği oluşturmak da mümkündür.

Not

Türün WeakReferenceMessenger kullanılması daha basit olduğundan ve kitaplıktaki MvvmLight messenger türünün davranışıyla eşleşeceğinden, MVVM Araç Seti'ndeki tür tarafından ObservableRecipient kullanılan varsayılan türdür. StrongReferenceType yine de kullanılabilir, bu sınıfın oluşturucusunun bir örneği geçirilerek.

İleti gönderme ve alma

Aşağıdaki topluluklara bir göz atın:

// Create a message
public class LoggedInUserChangedMessage : ValueChangedMessage<User>
{
    public LoggedInUserChangedMessage(User user) : base(user)
    {        
    }
}

// Register a message in some module
WeakReferenceMessenger.Default.Register<LoggedInUserChangedMessage>(this, (r, m) =>
{
    // Handle the message here, with r being the recipient and m being the
    // input message. Using the recipient passed as input makes it so that
    // the lambda expression doesn't capture "this", improving performance.
});

// Send a message from some other module
WeakReferenceMessenger.Default.Send(new LoggedInUserChangedMessage(user));

Bu ileti türünün, şu anda günlüğe kaydedilen kullanıcının kullanıcı adı ve profil görüntüsüyle bir üst bilgi, konuşma listesini içeren bir panel ve seçiliyse geçerli konuşmadan gelen iletilerin bulunduğu başka bir paneli görüntüleyen basit bir mesajlaşma uygulamasında kullanıldığını düşünelim. Bu üç bölümün sırasıyla ve ConversationViewModel türleri tarafından HeaderViewModelConversationsListViewModel desteklendiği düşünelim. Bu senaryoda, LoggedInUserChangedMessage bir oturum açma işlemi tamamlandıktan sonra ileti tarafından HeaderViewModel gönderilebilir ve diğer her iki görünüm modeli de işleyicileri kaydedebilir. Örneğin, ConversationsListViewModel yeni kullanıcının konuşma listesini yükler ve ConversationViewModel varsa yalnızca geçerli konuşmayı kapatır.

Örnek, IMessenger tüm kayıtlı alıcılara ileti teslim etme işlemini üstlenir. Alıcının belirli bir türe ait iletilere abone olabileceğini unutmayın. Devralınan ileti türlerinin MVVM Araç Seti tarafından sağlanan varsayılan IMessenger uygulamalarda kayıtlı olmadığını unutmayın.

Bir alıcıya artık ihtiyaç duyulmadığında, ileti almayı durdurabilmesi için kaydını kaldırmanız gerekir. kaydı ileti türüne, kayıt belirteciyle veya alıcıya göre kaldırabilirsiniz:

// Unregisters the recipient from a message type
WeakReferenceMessenger.Default.Unregister<LoggedInUserChangedMessage>(this);

// Unregisters the recipient from a message type in a specified channel
WeakReferenceMessenger.Default.Unregister<LoggedInUserChangedMessage, int>(this, 42);

// Unregister the recipient from all messages, across all channels
WeakReferenceMessenger.Default.UnregisterAll(this);

Uyarı

Daha önce belirtildiği gibi, alıcıları izlemek için zayıf başvurular kullandığından, türü kullanırken WeakReferenceMessenger bu kesinlikle gerekli değildir; bu, kullanılmayan alıcıların hala etkin ileti işleyicileri olsa bile çöp toplama için uygun olacağı anlamına gelir. Yine de performansları geliştirmek için aboneliklerini kaldırmak iyi bir uygulamadır. Öte yandan, StrongReferenceMessenger uygulama kayıtlı alıcıları izlemek için güçlü başvurular kullanır. Bu, performans nedeniyle yapılır ve bellek sızıntılarını önlemek için kayıtlı her alıcının el ile kaydının kaldırılmış olması gerektiği anlamına gelir. Yani, bir alıcı kayıtlı olduğu sürece, StrongReferenceMessenger kullanımdaki örnek etkin bir başvuruyu tutar ve bu da çöp toplayıcının bu örneği toplamasını engeller. Bunu el ile işleyebilir veya varsayılan olarak devre dışı bırakıldığında alıcı için tüm ileti kayıtlarının kaldırılmasını otomatik olarak üstlenen öğesinden ObservableRecipientdevralabilirsiniz (bu konuda daha fazla bilgi için bkz. belgeler açık ObservableRecipient ).

İleti işleyicilerini kaydetmek için arabirimini IRecipient<TMessage> kullanmak da mümkündür. Bu durumda, her alıcının belirli bir ileti türü için arabirimi uygulaması ve iletileri alırken çağrılacak bir Receive(TMessage) yöntem sağlaması gerekir, örneğin:

// Create a message
public class MyRecipient : IRecipient<LoggedInUserChangedMessage>
{
    public void Receive(LoggedInUserChangedMessage message)
    {
        // Handle the message here...   
    }
}

// Register that specific message...
WeakReferenceMessenger.Default.Register<LoggedInUserChangedMessage>(this);

// ...or alternatively, register all declared handlers
WeakReferenceMessenger.Default.RegisterAll(this);

// Send a message from some other module
WeakReferenceMessenger.Default.Send(new LoggedInUserChangedMessage(user));

İstek iletilerini kullanma

Messenger örneklerinin bir diğer kullanışlı özelliği de bir modülden diğerine değer istemek için kullanılabilmesidir. Bunu yapmak için paket aşağıdaki gibi kullanılabilecek bir temel RequestMessage<T> sınıf içerir:

// Create a message
public class LoggedInUserRequestMessage : RequestMessage<User>
{
}

// Register the receiver in a module
WeakReferenceMessenger.Default.Register<MyViewModel, LoggedInUserRequestMessage>(this, (r, m) =>
{
    // Assume that "CurrentUser" is a private member in our viewmodel.
    // As before, we're accessing it through the recipient passed as
    // input to the handler, to avoid capturing "this" in the delegate.
    m.Reply(r.CurrentUser);
});

// Request the value from another module
User user = WeakReferenceMessenger.Default.Send<LoggedInUserRequestMessage>();

sınıfı, RequestMessage<T> içindeki nesnesine User dönüştürmeyi mümkün kılan örtük bir LoggedInUserRequestMessage dönüştürücü içerir. Bu ayrıca ileti için bir yanıt alınıp alınmadığını denetler ve durum böyle değilse bir özel durum oluşturur. Bu zorunlu yanıt garantisi olmadan istek iletileri göndermek de mümkündür: Yalnızca döndürülen iletiyi yerel bir değişkende depolayın ve ardından yanıt değerinin kullanılabilir olup olmadığını el ile denetleyin. Bunun yapılması, yöntem döndürdüğünde Send yanıt alınmazsa otomatik özel durumu tetiklemez.

Aynı ad alanı, diğer senaryolar için temel istekler iletisini de içerir: AsyncRequestMessage<T>, CollectionRequestMessage<T> ve AsyncCollectionRequestMessage<T>. Zaman uyumsuz istek iletisini şu şekilde kullanabilirsiniz:

// Create a message
public class LoggedInUserRequestMessage : AsyncRequestMessage<User>
{
}

// Register the receiver in a module
WeakReferenceMessenger.Default.Register<MyViewModel, LoggedInUserRequestMessage>(this, (r, m) =>
{
    m.Reply(r.GetCurrentUserAsync()); // We're replying with a Task<User>
});

// Request the value from another module (we can directly await on the request)
User user = await WeakReferenceMessenger.Default.Send<LoggedInUserRequestMessage>();

Örnekler