[Prism] Composite Application Guidance for WPF (8) -- event

Source: Internet
Author: User
Tags eventbase

 [Prism] Composite Application Guidance for WPF (8) -- event
Zhou yinhui


the prism event is not straight use C # event or WPF routedevent, but compositewpfevent. Let's talk about it briefly today

1. Why is it completely new?Compositewpfevent, instead of C # event or WPF routedevent?
OriginalCause 1: disconnect the coupling between the event publisher and event subscriber..For example, module A needs to subscribe to a certain period of time in Module B, while module A does not directly reference Module B, but communicates with module A through generic dependency injection, therefore, you cannot subscribe to events during compilation.
Event publishing and registration are managed in a unified manner through eventaggregator, which serves as a bridge between subscriber and subscriber. Regarding eventaggregator, we will talk about it later.
However, it is worth mentioning that compositewpfevent focuses more on the event communication between modules. It is not used to replace the C # event and the routedevent of WPF, they are at different levels.

2, Eventaggregator
Prism uses a aggregator called eventaggregator to centrally manage events (compositewpfevent ).
This is actually a common mode. Its idea is relatively simple and provides instances of all events:
/// <Summary>
/// Define an interface for obtaining the instance of the Event Type
/// </Summary>
Public interface ieventaggregator
{
/// <Summary>
/// Obtain an instance of the Event Type
/// </Summary>
/// <Typeparam name = "teventtype"> obtain the event type of the instance </typeparam>
/// An instance of the <returns> event type <typeparamref name = "teventtype"/>. </returns>
[System. Diagnostics. codeanalysis. suppressmessage ("Microsoft. Design", "ca1004: genericmethodsshouldprovidetypeparameter")]
Teventtype getevent <teventtype> () Where teventtype: eventbase;
}
All event publishers and Subscribers get events from eventaggregator for publishing and subscription. The publisher does not care who the subscriber is,
The subscriber does not care who the publisher is. The same event can have different publishers, and the same event can have multiple subscribers. This forms a many-to-many relationship.
However, someone may ask, what should I do when I need to specify the publisher of an event, just like the sender parameter in a common event?
Simple: the event can pass any type of tplayload parameter (equivalent to xxxeventargs)
For eventaggregator mode, you can refer to here http://martinfowler.com/eaaDev/EventAggregator.html
In prism, eventaggregator is added to a container as a basic service.

3. How to create and publish an event

Public class loginsucessedeventargs
{
}

Public class loginsucessedevent: compositewpfevent <loginsucessedeventargs>
{
}

First, create a parameter type to be passed in the event, which can be a simple type such as string or a custom owner type. It is only an object that contains data,
So it is not necessary to inherit from eventargs like C #
Secondly, create a custom xxxevent, which inherits from compositewpfevent <t>, where T is the parameter you want to pass;
Compositewpfevent is an implementation of the observer mode. It naturally implements basic methods such as subscription and Unsubscription,
This inheritance method prevents you from manually implementing an observer mode for every event.

Can C # events use + = and-= to subscribe to and cancel a subscription? Why rewrite the observer mode?
Compositewpfevent provides more advanced functions than the C # event:
Callback of the event processor within the specified Thread
Three methods are provided: publishing thread, UI thread, and background thread (called by a new backgroundworker). See the following enumeration definition:

/// <Summary>
/// Specify the thread on which to call the <see CREF = "compositewpfevent {tpayload}"/> subscription
/// </Summary>
Public Enum threadoption
{
/// <Summary>
/// The call will occur on the same thread as when <see CREF = "compositewpfevent {tpayload}"/> is released.
/// </Summary>
Publisherthread,

/// <Summary>
/// Call will occur on the UI thread
/// </Summary>
Uithread,

/// <Summary>
/// Asynchronous call will be performed on the background thread
/// </Summary>
Backgroundthread
}

Whether to retain strong or weak references to subscribers.
By default, weak references are retained. If a strong reference is specified, the subscriber will not be recycled by memory unless the subscription is canceled manually.
The event acceptance filter can be specified..
Generally, If we subscribe to an event, the subscriber will always receive the message when the event is triggered, but this is not always useful,
In this case, you can provide a filter to notify the event publisher to only notify you of events that meet certain conditions.
This is very useful. In my coding experience, many times I have to give up C # event to achieve this function.

Refer to the followingCode:

Internal class loginmodule: imodule
{
Private readonly iregionmanager regionmanager;
Private readonly ieventaggregator eventaggregator;

Public loginmodule (iregionmanager regionmanager, ieventaggregator eventaggregator)
{
This. regionmanager = regionmanager;
This. eventaggregator = eventaggregator;
}

# Region imodule members

Public void initialize ()
{
Iregion region = regionmanager. Regions [regions. loginregionname];

If (region! = NULL)
{
VaR loginview = new defaultloginview ();

Loginview. loginsucessed + = loginview_loginsucessed;

region. Add (loginview);
region. Activate (loginview);
}< BR >}

Void loginview_loginsucessed (Object sender, loginsucessedeventargs E)
{
If (eventaggregator! = NULL)
{
Eventaggregator. getevent <loginsucessedevent> (). Publish (New loginsucessedeventargs ());
}
}

# Endregion
}

We use the constructor injection method like public loginmodule (iregionmanager regionmanager, ieventaggregator eventaggregator ).
To get eventaggregator, and then we can get the event we want to use from eventaggregator, and then release it in the following form:
Eventaggregator. getevent <loginsucessedevent> (). Publish (New loginsucessedeventargs ());

Eventaggregator obtains the Custom Event Type instance by reflection and in the form of a singleton by default,
Open the prism Source code , We can see that it is implemented in this way
Public teventtype getevent <teventtype> () Where teventtype: eventbase
{
VaR eventinstance = _ Events. firstordefault (EVT => EVT. GetType () = typeof (teventtype) as teventtype;
If (eventinstance = NULL)
{
Eventinstance = activator. createinstance <teventtype> ();
_ Events. Add (eventinstance );
}
Return eventinstance;
}

 

4. How to subscribe to events
It is easy to get the event instance from eventaggregator and then call the subscribe method.
The meanings of parameters of the subscribe method are as follows:
/// <Summary>
/// Add an event subscription
/// </Summary>
/// <Param name = "action"> action to be executed when an event is published </param>
/// <Param name = "threadoption"> specifies which thread will receive the callback of this proxy. </param>
/// <Param name = "keepsubscriberreferencealive"> when it is <see langword = "true"/>, <seealso CREF = "compositewpfevent {tpayload}"/> the subscriber will be referenced so that it will not be recycled as garbage. </param>
/// <Param name = "filter"> filter used to determine whether the subscriber receives the event. </param>
/// <Returns> <see CREF = "subscriptiontoken"/> </returns>
/// <Remarks>
/// If <paramref name = "keepsubscriberreferencealive"/> is set to <see langword = "false"/>, <see CREF = "compositewpfevent {tpayload}"/> maintain the <seealso CREF = "weakreference"/>
/// If no weak reference is used (<paramref name = "keepsubscriberreferencealive"/> is <see langword = "true"/>,
/// When a dispose subscriber is present as an event, UNSUBSCRIBE must be called to avoid Memory leakage or other exceptions.
/// The compositewpfevent set is thread-safe.
/// </Remarks>
Public Virtual subscriptiontoken subscribe (Action <tpayload> action, threadoption, bool keepsubscriberreferencealive, predicate <tpayload> filter)

Of course, you can also use the unsubscribe method to cancel the subscription.

 

5. What is the difference between the event and the cab event?
In cab, we generally use the following method to subscribe to and register events:

[Eventpublication ("Event: // myeventsignature", eventscope. Global)]
Event eventhandler <Object> myevent;

Public void raisemyevent ()
{
// Fire the event as a normal event
If myevent! = NULL)
{
Myevent (this, someobj );
}
}

[Eventsubcategory ("Event: // myeventsignature", eventscope. Global)]
Public void onmyevent (Object sender, object someobj)

{

}

This has an obvious drawback: the correctness of event subscription and release cannot be checked during compilation.
The reason is that we use attribute to mark the release and subscription events, and use magic string such as "Event: // myeventsignature.
If we write it as an incorrect signature such as Event: // mywrongeventsignature, it cannot be found during compilation. Other disadvantages of hard-coded strings should not be mentioned.
Another drawback is that cab needs to scan for whether each event has eventpublicationattribute and whether each method has eventsubscriptionattribute attribute to determine whether the event is published and subscribed. The impact on performance cannot be underestimated.
Prism avoids these problems by inheriting from compositewpfevent to form a strongly typed event type (rather than a simple string.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.