EventPublication and EventSubscription

Jul 23, 2008 at 3:14 AM
Hello,

1) I think that a way of using event publication and event subscription mechanism has been changed in Prism. May I know why? If it's still the same, Could you please give me an example how to use SCSF style "event subscription and event publication" in Prism?

2)  The following is the way that we used to use in SCSF. How can I get the same in Prism?

[EventSubscription(EventTopicNames.CustomerSelected, ThreadOption.UserInterface)]
public void WorkWithCustomer(object sender, EventArgs<Customer> e)
{
 }

[EventPublication(EventTopicNames.CustomerSelected, PublicationScope.Global)]
public event EventHandler<EventArgs> CustomerSelected;
public void WorkWithCustomer(Customer customer)
{
if (CustomerSelected != null)
CustomerSelected(this, new EventArgs<Customer>(customer));
}

3) Why do I need to create my own event class and my own eventargs class in order to use the event pub/sup in Prism? We tried to create one generic event class "SimpleAction" and generic eventargs "SimplePayLoad" in our project. The problem is that we can't specify the id of event. How can I specify the id of event?


Thanks in advance.
Jul 25, 2008 at 10:13 AM
The SCSF way of event publication and subscription doesn't work in CompositeWPF. Instead they introduced the CompositeWpfEvent base class.
Sadly you can't specify an event ID but are required to create a subclass instead. There is no extension available at this point to change this.
Jul 25, 2008 at 12:57 PM
To get the same sort of behavior, your subclass will need to expose an id property, and then when you subscribe to your message, use the predicate parm to say you only want messages with a certain id.

Or you could tell it you want messages with a particular id range, or messages that meet whatever criteria you want to check on exposed properties.  Very powerfull.  Much better than the simple string check done in CAB.

Just my opinion.
Paul
Jul 25, 2008 at 3:11 PM
Edited Jul 25, 2008 at 3:15 PM
[WMeints] The SCSF way of event publication and subscription doesn't work in CompositeWPF.

You can make it work as it does in SCSF with a little work.  The http://www.CodePlex.com/Unity source code provides an event broker sample.  
On the following link I apply it in 7 steps to the CompositeWPF Commanding solution provided with the CWPF source.  Only steps 3, 4, 6 and 7
may apply to your requirements.

http://www.codeplex.com/CompositeWPF/Thread/View.aspx?ThreadId=31598
Jul 28, 2008 at 6:12 AM
Edited Jul 28, 2008 at 6:37 AM
Thanks.
Hi Paul,

>>>r you could tell it you want messages with a particular id range, or messages that meet whatever criteria you want to check on exposed properties.  Very powerfull.  Much better than the simple string check done in CAB.

You mean, I should added one property called ID on Event Class?

Hi BillKrat,

I tried the way that you mentioned. But the PreBuildUp of EventBrokerReflectionStrategy class doesn't get called. What would be the problem?
Jul 28, 2008 at 11:09 AM
On your subclass, you can add whatever properties you want.  If you want to use an id to determine if a message is for a particular subscriber, define an id property.  Make it an int, a string, or another complete object.  Then when you subscribe to the message, use the predicate, working with the property, to filter the messages for a particular subscriber.  This way you are not limited to just a string compare to see if you get a message.  You could look for a string, or an int, or a range of ints, or whatever expression you can put into the predicate.
Jul 28, 2008 at 9:15 PM
Hi Michaelsync,   If the PreBuildUp of a Strategy is not executed it is mostly likely that it isn't a registered strategy.  Unity exposes the context's strategy object (for AddNew) via the UnityContainerExtension; in our case the SimpleEventBrokerExtension.   If you'll examine the SimpleEventBrokerExtension.cs file you'll see it adds both the EventBrokerReflectionStrategy as well as the EventBrokerWireupStrategy.   You'll want to add an .AddNewExtension<SimpleEventBrokerExtension>() to your unity container, an example follows:

 

IUnityContainer container = new UnityContainer()
    
.AddNewExtension<SimpleEventBrokerExtension>()
     .RegisterType<
ILogger, StatusLogger>();

 

In response to:
[michaelsync] I tried the way that you mentioned. But the PreBuildUp of EventBrokerReflectionStrategy class doesn't get called. What would be the problem?
Aug 1, 2008 at 3:08 AM
Sorry for late reply. I've been trying for that these days and still not working the way that I want.

Hi Paul,

>>On your subclass, you can add whatever properties you want.  If you want to use an id to determine if a message is for a particular subscriber, define an id property.  Make it an int, a string, or another complete object.  Then when you subscribe to the message, use the predicate, working with the property, to filter the messages for a particular subscriber.  This way you are not limited to just a string compare to see if you get a message.  You could look for a string, or an int, or a range of ints, or whatever expression you can put into the predicate

Yes. Thanks. I did that and it works. But it happened to me to add ID in EventArg (Payloads) (not Event (SimpleAction)) class.

Hi Bill,

>>IUnityContainer container = new UnityContainer()
    
.AddNewExtension<SimpleEventBrokerExtension>()
     .RegisterType<
ILogger, StatusLogger>();

Since I'm using Prism, I can't initialize that way. But I tried the following way.

 class BootStrapper : UnityBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            Container.AddNewExtension<SimpleEventBrokerExtension>();           // it doesn't work. 
            Shell shell = Container.Resolve<Shell>();
            shell.Show();
            return shell;
        }

        protected override IModuleEnumerator GetModuleEnumerator()
        {
            //return new ConfigurationModuleEnumerator();
            ConfigurationStore store = new ConfigurationStore();
            return new ConfigurationModuleEnumerator(store);

        }
    }
Aug 1, 2008 at 1:20 PM
the predicate works against the TPayLoad in the CompositeWpfEvent<TPayLoad>.  So the values you want to filter on in the predicate should be there.

And just in case you hadnt seen it, in the Composite Application Guidance for WPF help file, in the Development Activities sections, they give examples of how to create and publish events
and how to subscribe and unsubscribe to events.  In the filter section of those Activites, they have examples of this using a FundAddedEvent and a FundOrder. 

They give a predicate example of "fundOrder => fundOrder.CustomerId == _customerId". 

Paul
Aug 2, 2008 at 4:17 PM
Hi MichaelSync,  I created a CompositeWPF (aka Prism) demo that utilizes SCSF style event publication/subscription via Unity. 
Source and flash demo are available HERE.  
Aug 5, 2008 at 6:47 AM
Edited Aug 5, 2008 at 6:48 AM
@Michael

The reason for the base class is to enable compile-time checking. In CAB there is no guarantee at compile time that the publisher and subscriber are correctly wired.
A common pattern there is to have a shared set of string constants that define the event name. This however does not ensure that the proper arguments are passed by the publisher or the subscriber.
If the publisher event and subscriber handlers do not have the right signatures, then they will fail at runtime. The only way to ensure they are correct is through convention. In a large system with many events
this can be problematic. With the CompositeWPFEvent however, this is not the case. Because the class is generic, the Publish and Subscribe methods will only allow passing in parameters of type TPayLoad.
Additionally this also enforces the type of the subscription filters. Finally having a type removes embedding constants throughout the application.

Hope this clarifies
Glenn