SPRNET-547 - Add Unsubscribe functionality to IEventRegistry

This commit is contained in:
markpollack
2008-10-13 15:32:38 +00:00
parent 33fd079580
commit 54a059627b
6 changed files with 230 additions and 94 deletions

View File

@@ -1821,6 +1821,31 @@ namespace Spring.Context.Support
_eventRegistry.Subscribe(subscriber, targetSourceType);
}
/// <summary>
/// Unsubscribes to <b>all</b> events published, if the subscriber
/// implmenets compatible handler methods.
/// </summary>
/// <param name="subscriber">The subscriber to use</param>
public void Unsubscribe(object subscriber)
{
_eventRegistry.Unsubscribe(subscriber);
}
/// <summary>
/// Unsubscribes to the published events of all objects of a given
/// <see cref="System.Type"/>, if the subscriber implements
/// compatible handler methods.
/// </summary>
/// <param name="subscriber">The subscriber to use.</param>
/// <param name="targetSourceType">
/// The target <see cref="System.Type"/> to unsubscribe from
/// </param>
public void Unsubscribe(object subscriber, Type targetSourceType)
{
_eventRegistry.Unsubscribe(subscriber, targetSourceType);
}
#endregion
/// <summary>

View File

@@ -53,6 +53,24 @@ namespace Spring.Objects.Events
/// <param name="targetSourceType">
/// The target <see cref="System.Type"/> to subscribe to.
/// </param>
void Subscribe(object subscriber, Type targetSourceType);
void Subscribe(object subscriber, Type targetSourceType);
/// <summary>
/// Unsubscribes to <b>all</b> events published, if the subscriber
/// implmenets compatible handler methods.
/// </summary>
/// <param name="subscriber">The subscriber to use</param>
void Unsubscribe(object subscriber);
/// <summary>
/// Unsubscribes to the published events of all objects of a given
/// <see cref="System.Type"/>, if the subscriber implements
/// compatible handler methods.
/// </summary>
/// <param name="subscriber">The subscriber to use.</param>
/// <param name="targetSourceType">
/// The target <see cref="System.Type"/> to unsubscribe from
/// </param>
void Unsubscribe(object subscriber, Type targetSourceType);
}
}

View File

@@ -28,97 +28,138 @@ using System.Reflection;
namespace Spring.Objects.Events.Support
{
/// <summary>
/// Default implementation of the <see cref="Spring.Objects.Events.IEventRegistry"/>
/// interface.
/// </summary>
/// <author>Griffin Caprio</author>
public class EventRegistry : IEventRegistry
{
private IList _publishers;
/// <summary>
/// Default implementation of the <see cref="Spring.Objects.Events.IEventRegistry"/>
/// interface.
/// </summary>
/// <author>Griffin Caprio</author>
public class EventRegistry : IEventRegistry
{
private IList _publishers;
/// <summary>
/// Creates a new instance of the EventRegistry class.
/// </summary>
public EventRegistry()
{
_publishers = new ArrayList();
}
/// <summary>
/// Creates a new instance of the EventRegistry class.
/// </summary>
public EventRegistry()
{
_publishers = new ArrayList();
}
/// <summary>
/// The list of event publishers.
/// </summary>
/// <value>The list of event publishers.</value>
protected IList Publishers
{
get { return _publishers; }
}
/// <summary>
/// The list of event publishers.
/// </summary>
/// <value>The list of event publishers.</value>
protected IList Publishers
{
get { return _publishers; }
}
/// <summary>
/// Adds the input object to the list of publishers.
/// </summary>
/// <remarks>
/// This publishes <b>all</b> events of the source object to any object
/// wishing to subscribe
/// </remarks>
/// <param name="source">The source object to publish.</param>
public virtual void PublishEvents(object source)
{
Publishers.Add(source);
}
/// <summary>
/// Adds the input object to the list of publishers.
/// </summary>
/// <remarks>
/// This publishes <b>all</b> events of the source object to any object
/// wishing to subscribe
/// </remarks>
/// <param name="source">The source object to publish.</param>
public virtual void PublishEvents(object source)
{
Publishers.Add(source);
}
/// <summary>
/// Subscribes to <b>all</b> events published, if the subscriber implements
/// compatible handler methods.
/// </summary>
/// <param name="subscriber">The subscriber to use.</param>
public virtual void Subscribe(object subscriber)
{
Subscribe(subscriber, null);
}
/// <summary>
/// Subscribes to <b>all</b> events published, if the subscriber implements
/// compatible handler methods.
/// </summary>
/// <param name="subscriber">The subscriber to use.</param>
public virtual void Subscribe(object subscriber)
{
Subscribe(subscriber, null);
}
/// <summary>
/// Subscribes to published events of all objects of a given type, if the
/// subscriber implements compatible handler methods.
/// </summary>
/// <param name="subscriber">The subscriber to use.</param>
/// <param name="sourceType">
/// The target <see cref="System.Type"/> to subscribe to.
/// </param>
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));
}
}
}
}
/// <summary>
/// Subscribes to published events of all objects of a given type, if the
/// subscriber implements compatible handler methods.
/// </summary>
/// <param name="subscriber">The subscriber to use.</param>
/// <param name="sourceType">
/// The target <see cref="System.Type"/> to subscribe to.
/// </param>
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);
}
}
}
/// <summary>
/// Unsubscribes to <b>all</b> events published, if the subscriber
/// implmenets compatible handler methods.
/// </summary>
/// <param name="subscriber">The subscriber to use</param>
public virtual void Unsubscribe(object subscriber)
{
Unsubscribe(subscriber, null);
}
/// <summary>
/// Unsubscribes to the published events of all objects of a given
/// <see cref="System.Type"/>, if the subscriber implements
/// compatible handler methods.
/// </summary>
/// <param name="subscriber">The subscriber to use.</param>
/// <param name="sourceType">The target <see cref="System.Type"/> to unsubscribe from</param>
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));
}
}
}
}
}
}

View File

@@ -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
}
}

View File

@@ -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)
{

View File

@@ -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()
{