polishing

This commit is contained in:
eeichinger
2009-10-15 17:14:45 +00:00
parent 04ef351712
commit ccc64cbf73
6 changed files with 129 additions and 33 deletions

View File

@@ -49,7 +49,7 @@ namespace Spring.Context.Events
Closed
} ;
private ContextEvent _contextEvent;
private readonly ContextEvent _contextEvent;
/// <summary>
/// Creates a new instance of the ContextEventArgs class to represent the
@@ -79,5 +79,29 @@ namespace Spring.Context.Events
CultureInfo.InvariantCulture,
"{0} [{1}]", GetType().Name, Event);
}
}
}
/// <summary>
/// Event object sent to listeners registered with an
/// <see cref="Spring.Context.IApplicationContext"/> to inform them of
/// context <see cref="ContextEventArgs.ContextEvent.Refreshed"/> lifecycle event.
/// </summary>
public class ContextRefreshedEventArgs : ContextEventArgs
{
public ContextRefreshedEventArgs() : base(ContextEvent.Refreshed)
{
}
}
/// <summary>
/// Event object sent to listeners registered with an
/// <see cref="Spring.Context.IApplicationContext"/> to inform them of
/// context <see cref="ContextEventArgs.ContextEvent.Closed"/> lifecycle event.
/// </summary>
public class ContextClosedEventArgs : ContextEventArgs
{
public ContextClosedEventArgs() : base(ContextEvent.Closed)
{
}
}
}

View File

@@ -145,9 +145,11 @@ namespace Spring.Context.Support
private string _name;
private DateTime _startupDate;
private readonly bool _isCaseSensitive;
private EventRaiser _eventRaiser;
#endregion
#region Constructor (s) / Destructor
/// <summary>
@@ -202,6 +204,7 @@ namespace Spring.Context.Support
_name = (StringUtils.IsNullOrEmpty(name)) ? DefaultRootContextName : name;
_isCaseSensitive = caseSensitive;
_parentApplicationContext = parentApplicationContext;
EventRaiser = CreateEventRaiser();
_objectFactoryPostProcessors = new ArrayList();
_defaultObjectPostProcessors = new ArrayList();
AddDefaultObjectPostProcessor(new ObjectPostProcessorChecker());
@@ -244,10 +247,10 @@ namespace Spring.Context.Support
#endregion
// TODO: any reason, why Closed event is raised before destroying objectfactory?
new DefensiveEventRaiser().Raise(
ContextEvent, this,
new ContextEventArgs(ContextEventArgs.ContextEvent.Closed));
// Closed event is raised before destroying objectfactory to enable registered IApplicationEventListeners
// to handle the event before they get disposed.
PublishEvent(this, new ContextClosedEventArgs());
ObjectFactory.Dispose();
}
@@ -281,6 +284,18 @@ namespace Spring.Context.Support
get { return this; }
}
/// <summary>
/// Set the <see cref="EventRaiser"/> to be used by this context.
/// </summary>
public EventRaiser EventRaiser
{
set
{
AssertUtils.ArgumentNotNull(value, "EventRaiser");
_eventRaiser = value;
}
}
/// <summary>
/// The timestamp when this context was first loaded.
/// </summary>
@@ -387,7 +402,15 @@ namespace Spring.Context.Support
/// </param>
protected virtual void OnContextEvent(object source, ApplicationEventArgs e)
{
new DefensiveEventRaiser().Raise(ContextEvent, source, e);
_eventRaiser.Raise(ContextEvent, source, e);
}
/// <summary>
/// Create the <see cref="EventRaiser"/> strategy to be used
/// </summary>
protected virtual EventRaiser CreateEventRaiser()
{
return new DefensiveEventRaiser();
}
/// <summary>
@@ -444,6 +467,7 @@ namespace Spring.Context.Support
/// </summary>
protected virtual void OnPostRefresh()
{
PublishEvent(this, new ContextRefreshedEventArgs());
}
/// <summary>
@@ -864,10 +888,11 @@ namespace Spring.Context.Support
RegisterObjectPostProcessors(objectFactory);
InitEventRegistry();
InitMessageSource();
OnRefresh();
RefreshApplicationEventListeners();
OnRefresh();
#region Instrumentation
if (log.IsDebugEnabled)
@@ -881,10 +906,6 @@ namespace Spring.Context.Support
OnPostRefresh();
new DefensiveEventRaiser().Raise(
ContextEvent, this,
new ContextEventArgs(ContextEventArgs.ContextEvent.Refreshed));
#region Instrumentation
if (log.IsInfoEnabled)

View File

@@ -35,7 +35,7 @@ namespace Spring.Objects.Events.Support
/// <author>Griffin Caprio</author>
public class EventRegistry : IEventRegistry
{
private IList _publishers;
private readonly IList _publishers;
/// <summary>
/// Creates a new instance of the EventRegistry class.

View File

@@ -21,7 +21,10 @@
#region Imports
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using Common.Logging;
#endregion
@@ -33,6 +36,16 @@ namespace Spring.Util
/// <author>Rick Evans</author>
public class EventRaiser
{
protected readonly ILog Log;
/// <summary>
/// Create a new EventRaiser instance
/// </summary>
public EventRaiser()
{
Log = LogManager.GetLogger(this.GetType());
}
/// <summary>
/// Raises the event encapsulated by the supplied
/// <paramref name="source"/>, passing the supplied <paramref name="arguments"/>
@@ -40,17 +53,23 @@ namespace Spring.Util
/// </summary>
/// <param name="source">The event to be raised.</param>
/// <param name="arguments">The arguments to the event.</param>
public virtual void Raise (Delegate source, params object [] arguments)
/// <returns>a map of sink/exception entries that occurred during event raising</returns>
public virtual IDictionary Raise (Delegate source, params object [] arguments)
{
if (source == null)
{
return;
return null;
}
IDictionary exceptions = null;
Delegate [] delegates = source.GetInvocationList ();
foreach (Delegate sink in delegates)
{
Invoke (sink, arguments);
exceptions = Invoke (sink, arguments, exceptions);
}
return exceptions;
}
/// <summary>
@@ -59,11 +78,13 @@ namespace Spring.Util
/// </summary>
/// <param name="sink">The sink to be invoked.</param>
/// <param name="arguments">The arguments to the sink.</param>
protected virtual void Invoke (Delegate sink, object [] arguments)
/// <param name="exceptions">the map of sink/exception entries to add any exception to</param>
protected virtual IDictionary Invoke (Delegate sink, object [] arguments, IDictionary exceptions)
{
try
{
sink.DynamicInvoke (arguments);
return exceptions;
}
catch (TargetInvocationException ex)
{
@@ -92,15 +113,20 @@ namespace Spring.Util
/// </summary>
/// <param name="sink">The sink to be invoked.</param>
/// <param name="arguments">The arguments to the sink.</param>
protected override void Invoke (Delegate sink, object [] arguments)
/// <param name="exceptions">the map of sink/exception entries to add any exception to</param>
protected override IDictionary Invoke(Delegate sink, object[] arguments, IDictionary exceptions)
{
try
{
sink.DynamicInvoke (arguments);
}
catch
catch(Exception ex)
{
Log.Warn("Error during raising an event from " + new StackTrace(), ex);
if (exceptions == null) exceptions = new Hashtable();
exceptions.Add(sink, ex);
}
return exceptions;
}
}
}

View File

@@ -21,28 +21,53 @@
#region Imports
using System;
using System.Collections;
using NUnit.Framework;
#endregion
namespace Spring.Util
{
/// <summary>
/// Unit tests for the DefensiveEventRaiser class.
/// <summary>
/// Unit tests for the DefensiveEventRaiser class.
/// </summary>
/// <author>Rick Evans</author>
[TestFixture]
[TestFixture]
public sealed class DefensiveEventRaiserTests
{
[Test]
public void RaiseSwallowsExceptionRaisedByHandlers ()
public void RaiseSwallowsExceptionRaisedByHandlers()
{
OneThirstyDude dude = new OneThirstyDude ();
Soda bru = new Soda ();
bru.Pop += new PopHandler (dude.HandlePopWithException);
bru.OnPop ("Iron Brew", new DefensiveEventRaiser ());
Assert.AreEqual ("Iron Brew", dude.Soda); // should have got through before exception was thrown
OneThirstyDude dude = new OneThirstyDude();
Soda bru = new Soda();
bru.Pop += new PopHandler(dude.HandlePopWithException);
bru.OnPop("Iron Brew", new DefensiveEventRaiser());
Assert.AreEqual("Iron Brew", dude.Soda); // should have got through before exception was thrown
}
}
#if NET_2_0
[Test]
public void RaiseSwallowsExceptionRaisedByHandlerButCallsAllOtherHandlers()
{
bool firstCall = false;
bool secondCall = false;
bool thirdCall = false;
OneThirstyDude dude = new OneThirstyDude();
Soda bru = new Soda();
bru.Pop += new PopHandler(delegate { firstCall = true; });
bru.Pop += new PopHandler(delegate { secondCall = true; throw new Exception(); });
bru.Pop += new PopHandler(delegate { thirdCall = true; });
DefensiveEventRaiser eventRaiser = new DefensiveEventRaiser();
IDictionary exceptions = bru.OnPop( "Iron Brew", eventRaiser );
Assert.AreEqual(1, exceptions.Count);
Assert.IsTrue(firstCall);
Assert.IsTrue(secondCall);
Assert.IsTrue(thirdCall);
}
#endif
}
}

View File

@@ -21,7 +21,7 @@
#region Imports
using System;
using System.Collections;
using NUnit.Framework;
#endregion
@@ -81,9 +81,9 @@ namespace Spring.Util
{
public event PopHandler Pop;
public void OnPop (string soda, EventRaiser raiser)
public IDictionary OnPop (string soda, EventRaiser raiser)
{
raiser.Raise (Pop, this, soda);
return raiser.Raise (Pop, this, soda);
}
public void OnPopWithBadNumberOfArguments (string soda, EventRaiser raiser)