From 54a059627bd6610765f801df0c851cd9b8dbcda3 Mon Sep 17 00:00:00 2001 From: markpollack Date: Mon, 13 Oct 2008 15:32:38 +0000 Subject: [PATCH] SPRNET-547 - Add Unsubscribe functionality to IEventRegistry --- .../Support/AbstractApplicationContext.cs | 25 ++ .../Objects/Events/IEventRegistry.cs | 20 +- .../Objects/Events/Support/EventRegistry.cs | 217 +++++++++++------- .../Spring.Core.Tests/Context/CommonTypes.cs | 17 +- .../Support/ApplicationObjectSupportTests.cs | 13 +- .../Events/Support/EventRegistryTests.cs | 32 ++- 6 files changed, 230 insertions(+), 94 deletions(-) diff --git a/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs b/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs index a9eba505..f8602d26 100644 --- a/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs +++ b/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs @@ -1821,6 +1821,31 @@ namespace Spring.Context.Support _eventRegistry.Subscribe(subscriber, targetSourceType); } + + /// + /// Unsubscribes to all events published, if the subscriber + /// implmenets compatible handler methods. + /// + /// The subscriber to use + public void Unsubscribe(object subscriber) + { + _eventRegistry.Unsubscribe(subscriber); + } + + /// + /// Unsubscribes to the published events of all objects of a given + /// , if the subscriber implements + /// compatible handler methods. + /// + /// The subscriber to use. + /// + /// The target to unsubscribe from + /// + public void Unsubscribe(object subscriber, Type targetSourceType) + { + _eventRegistry.Unsubscribe(subscriber, targetSourceType); + } + #endregion /// diff --git a/src/Spring/Spring.Core/Objects/Events/IEventRegistry.cs b/src/Spring/Spring.Core/Objects/Events/IEventRegistry.cs index be7c29a1..8bb7f259 100644 --- a/src/Spring/Spring.Core/Objects/Events/IEventRegistry.cs +++ b/src/Spring/Spring.Core/Objects/Events/IEventRegistry.cs @@ -53,6 +53,24 @@ namespace Spring.Objects.Events /// /// The target to subscribe to. /// - void Subscribe(object subscriber, Type targetSourceType); + void Subscribe(object subscriber, Type targetSourceType); + + /// + /// Unsubscribes to all events published, if the subscriber + /// implmenets compatible handler methods. + /// + /// The subscriber to use + void Unsubscribe(object subscriber); + + /// + /// Unsubscribes to the published events of all objects of a given + /// , if the subscriber implements + /// compatible handler methods. + /// + /// The subscriber to use. + /// + /// The target to unsubscribe from + /// + void Unsubscribe(object subscriber, Type targetSourceType); } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Events/Support/EventRegistry.cs b/src/Spring/Spring.Core/Objects/Events/Support/EventRegistry.cs index 55253488..53450e95 100644 --- a/src/Spring/Spring.Core/Objects/Events/Support/EventRegistry.cs +++ b/src/Spring/Spring.Core/Objects/Events/Support/EventRegistry.cs @@ -28,97 +28,138 @@ using System.Reflection; namespace Spring.Objects.Events.Support { - /// - /// Default implementation of the - /// interface. - /// - /// Griffin Caprio - public class EventRegistry : IEventRegistry - { - private IList _publishers; + /// + /// Default implementation of the + /// interface. + /// + /// Griffin Caprio + public class EventRegistry : IEventRegistry + { + private IList _publishers; - /// - /// Creates a new instance of the EventRegistry class. - /// - public EventRegistry() - { - _publishers = new ArrayList(); - } + /// + /// Creates a new instance of the EventRegistry class. + /// + public EventRegistry() + { + _publishers = new ArrayList(); + } - /// - /// The list of event publishers. - /// - /// The list of event publishers. - protected IList Publishers - { - get { return _publishers; } - } + /// + /// The list of event publishers. + /// + /// The list of event publishers. + protected IList Publishers + { + get { return _publishers; } + } - /// - /// Adds the input object to the list of publishers. - /// - /// - /// This publishes all events of the source object to any object - /// wishing to subscribe - /// - /// The source object to publish. - public virtual void PublishEvents(object source) - { - Publishers.Add(source); - } + /// + /// Adds the input object to the list of publishers. + /// + /// + /// This publishes all events of the source object to any object + /// wishing to subscribe + /// + /// The source object to publish. + public virtual void PublishEvents(object source) + { + Publishers.Add(source); + } - /// - /// Subscribes to all events published, if the subscriber implements - /// compatible handler methods. - /// - /// The subscriber to use. - public virtual void Subscribe(object subscriber) - { - Subscribe(subscriber, null); - } + /// + /// Subscribes to all events published, if the subscriber implements + /// compatible handler methods. + /// + /// The subscriber to use. + public virtual void Subscribe(object subscriber) + { + Subscribe(subscriber, null); + } - /// - /// Subscribes to published events of all objects of a given type, if the - /// subscriber implements compatible handler methods. - /// - /// The subscriber to use. - /// - /// The target to subscribe to. - /// - public virtual void Subscribe(object subscriber, Type sourceType) - { - Type currentSubscriberType = subscriber.GetType(); - foreach (object currentPublisher in _publishers) - { - if (null == sourceType - || sourceType.IsAssignableFrom(currentPublisher.GetType())) - { - wireSubscriberToPublisher( - currentPublisher, currentSubscriberType, subscriber); - } - } - } - - private static void wireSubscriberToPublisher( - object currentPublisher, Type currentSubscriberType, object subscriber) - { - Type currentPublisherType = currentPublisher.GetType(); - EventInfo[] events = currentPublisherType.GetEvents(); - foreach (EventInfo currentEvent in events) - { - Type eventHandlerType = currentEvent.EventHandlerType; - MethodInfo invoke = eventHandlerType.GetMethod("Invoke"); - MethodInfo eventHandler - = EventManipulationUtils.GetMethodInfoMatchingSignature( - invoke, currentSubscriberType); - if (eventHandler != null) - { - currentEvent.AddEventHandler( - currentPublisher, - EventManipulationUtils.GetHandlerDelegate( - eventHandlerType, subscriber, eventHandler)); - } - } - } - } + /// + /// Subscribes to published events of all objects of a given type, if the + /// subscriber implements compatible handler methods. + /// + /// The subscriber to use. + /// + /// The target to subscribe to. + /// + public virtual void Subscribe(object subscriber, Type sourceType) + { + Type currentSubscriberType = subscriber.GetType(); + foreach (object currentPublisher in _publishers) + { + if (null == sourceType + || sourceType.IsAssignableFrom(currentPublisher.GetType())) + { + WireOrUnwireSubscriberToPublisher( + currentPublisher, currentSubscriberType, subscriber, true); + } + } + } + + /// + /// Unsubscribes to all events published, if the subscriber + /// implmenets compatible handler methods. + /// + /// The subscriber to use + public virtual void Unsubscribe(object subscriber) + { + Unsubscribe(subscriber, null); + } + + /// + /// Unsubscribes to the published events of all objects of a given + /// , if the subscriber implements + /// compatible handler methods. + /// + /// The subscriber to use. + /// The target to unsubscribe from + public virtual void Unsubscribe(object subscriber, Type sourceType) + { + Type currentSubscriberType = subscriber.GetType(); + foreach (object currentPublisher in _publishers) + { + if (null == sourceType + || sourceType.IsAssignableFrom(currentPublisher.GetType())) + { + WireOrUnwireSubscriberToPublisher( + currentPublisher, currentSubscriberType, subscriber, false); + } + } + } + + private static void WireOrUnwireSubscriberToPublisher( + object currentPublisher, Type currentSubscriberType, object subscriber, bool wire) + { + Type currentPublisherType = currentPublisher.GetType(); + EventInfo[] events = currentPublisherType.GetEvents(); + foreach (EventInfo currentEvent in events) + { + Type eventHandlerType = currentEvent.EventHandlerType; + MethodInfo invoke = eventHandlerType.GetMethod("Invoke"); + MethodInfo eventHandler + = EventManipulationUtils.GetMethodInfoMatchingSignature( + invoke, currentSubscriberType); + if (eventHandler != null) + { + if (wire) + { + currentEvent.AddEventHandler( + currentPublisher, + EventManipulationUtils.GetHandlerDelegate( + eventHandlerType, subscriber, eventHandler)); + } + else + { + currentEvent.RemoveEventHandler( + currentPublisher, + EventManipulationUtils.GetHandlerDelegate( + eventHandlerType, subscriber, eventHandler)); + } + } + } + } + } } \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Context/CommonTypes.cs b/test/Spring/Spring.Core.Tests/Context/CommonTypes.cs index 7020d9f4..1bec58e6 100644 --- a/test/Spring/Spring.Core.Tests/Context/CommonTypes.cs +++ b/test/Spring/Spring.Core.Tests/Context/CommonTypes.cs @@ -584,11 +584,22 @@ namespace Spring.Context throw new NotImplementedException(); } - #endregion - public void PublishEvent(object sender, ApplicationEventArgs e) { throw new NotImplementedException(); } - } + + + public void Unsubscribe(object subscriber) + { + throw new NotImplementedException(); + } + + public void Unsubscribe(object subscriber, Type targetSourceType) + { + throw new NotImplementedException(); + } + + #endregion + } } \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs b/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs index b02ce052..adf2e81f 100644 --- a/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs +++ b/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs @@ -325,7 +325,18 @@ namespace Spring.Context.Support throw new NotImplementedException(); } - #endregion + + public void Unsubscribe(object subscriber) + { + throw new NotImplementedException(); + } + + public void Unsubscribe(object subscriber, Type targetSourceType) + { + throw new NotImplementedException(); + } + + #endregion public void PublishEvent(object sender, ApplicationEventArgs e) { diff --git a/test/Spring/Spring.Core.Tests/Objects/Events/Support/EventRegistryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Events/Support/EventRegistryTests.cs index 9de96b59..9e6774de 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Events/Support/EventRegistryTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Events/Support/EventRegistryTests.cs @@ -111,13 +111,20 @@ namespace Spring.Objects.Events.Support.Tests internal class SimpleSubscriber { + protected int _eventCount; + protected bool _eventRaised = false; public SimpleSubscriber() { } - public bool EventRaised + public int EventCount + { + get { return _eventCount; } + } + + public bool EventRaised { get { return _eventRaised; } } @@ -132,6 +139,7 @@ namespace Spring.Objects.Events.Support.Tests public void HandleClientEvents(object sender, MyClientEventArgs args) { _eventRaised = true; + _eventCount++; } } @@ -220,6 +228,28 @@ namespace Spring.Objects.Events.Support.Tests Assert.IsTrue(sub2.EventRaised, "Event Not Raised"); } + [Test] + public void PublishAllEventsMultipleSubscribersAndUnsubscribe() + { + IEventRegistry registry = new EventRegistry(); + SimpleClient client = new SimpleClient("PublishAllEvents"); + registry.PublishEvents(client); + EventSubscriber sub = new EventSubscriber(); + EventSubscriber sub2 = new EventSubscriber(); + registry.Subscribe(sub); + registry.Subscribe(sub2); + client.ClientMethodThatTriggersEvent(); + Assert.IsTrue(sub.EventRaised, "Event Not Raised"); + Assert.IsTrue(sub2.EventRaised, "Event Not Raised"); + Assert.AreEqual(1, sub.EventCount); + Assert.AreEqual(1, sub2.EventCount); + + registry.Unsubscribe(sub2); + client.ClientMethodThatTriggersEvent(); + Assert.AreEqual(2, sub.EventCount); + Assert.AreEqual(1, sub2.EventCount); + } + [Test] public void PublishAllEventsSubscribeToNamedEvents() {