Click here to Skip to main content
15,896,730 members
Articles / Programming Languages / C#

Tweaked Events

Rate me:
Please Sign up or sign in to vote.
4.83/5 (12 votes)
18 Dec 2010MIT18 min read 34.8K   289   41  
Framework for customizing events. Comes with Weak Events and Synced Events
using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace JpLabs.TweakedEvents
{
	/// TODO:
	/// - Implement a SyncedWeakEventEntry [DONE]
	/// - Consider more reusability of IEventEntryFactory instances [obsolete]
	/// - Consider changing IEventEntryFactory to a delegate [obsolete]
	/// - Review possible synchronization issue at event removing [obsolete by immutability]
	/// - Make all custom events immutable [DONE]
	/// - Use a Future to control the SynchronizationContext inside synced event entries [obsolete]
	/// - Find a way for the subscriber choose which type of custom event to use [DONE by implicit casting to EventHandler]
	/// - REVIEW: add and remove operations must be atomic operations (run in a synchronized context). [DONE by using Interlocked.CompareExchange]
	///		- i.e: when two threads are running 'add', one can neutralize the other
	/// - Problem: When removing an event entry, should I ignore disposed instances still present on the custom event?
	/// - Make synced events correctly handle WPF controls
	///		- Do WPF controls need synchronized events?
	///		- System.Windows.IWeakEventListener
	///	- Special custom event that stop calling handlers when HandledEventArgs.Handled is set
	///	- Generic way to combine custom events behavior (e.g. a Weak + Priority event)
	///	- Multicast WeakDelegate (problem is on the Invoke method)
	///	- Review WeakEventForwarderProvider.Forwarders dictionary. One entry per method is too much.
	///		- Can I get to one method per method signature? Unfortunately, no.
	///	- C# 4 Event implementation changes: http://blogs.msdn.com/cburrows/

	///	- Priority Events (http://stackoverflow.com/questions/1308478/)
	///	- Toggle Events
	///		- May be either On or Off;
	///		- When Raised, the event automatically turns On;
	///		- When a handler/entry is added, if the event is On, the new handler/entry is invoked with the last invocation args;
	///			- Issue: When to raise entry? At combination is wrong. At attribution is impossible(?).
	///	- Memento Events
	///		- Remembers all invocations;
	///		- When a handler/entry is added, the past invocations are repeated to the new handler/entry;
	/// - Pull Events
	///		- http://blogs.msdn.com/ericlippert/archive/2009/07/23/iterator-blocks-part-five-push-vs-pull.aspx
	///		- http://ayende.com/Blog/archive/2009/02/16/pull-vs.-push-models-for-ui-updates.aspx
	///		- http://www.balisage.net/Proceedings/vol3/html/Kay01/BalisageVol3-Kay01.html
	///		- Reactive Framework = http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx
	///		- Optional Middleware (a stream/queue of events)
	///		- Listen to events from more than one source
	///		- LINQ to filter events
	
	/* TODO: Pull events
	public interface IEventOccurrence
	{
		object Sender { get; }
		EventArgs Args { get; }
	}

	public interface IEventOccurrence<TEventArgs> where TEventArgs : EventArgs
	{
		object Sender { get; }
		TEventArgs Args { get; }
	}
	
	public interface IPullEvent : IEnumerable<IEventOccurrence>, IDisposable
	{
	}

	public interface IPullEvent<TEventArgs> : IEnumerable<IEventOccurrence<TEventArgs>>, IDisposable
	where TEventArgs : EventArgs
	{
	}
	//*/
	
	[ImmutableObject(true)]
	public interface ITweakedEvent
	{
		void Raise(object sender, EventArgs e);
	}
	
	/// <summary>
	/// Tweaked events implement a Custom Store for Event Delegates internally (http://msdn.microsoft.com/en-us/magazine/cc163533.aspx)
	/// </summary>
	[ImmutableObject(true)]
	public interface ITweakedEvent<TEventHandler> : ITweakedEvent where TEventHandler : class
	{
		bool IsEmpty();
		ITweakedEvent<TEventHandler> Clear();

		ITweakedEvent<TEventHandler> Combine(TEventHandler handler);
		ITweakedEvent<TEventHandler> Subtract(TEventHandler handler);
		ITweakedEvent<TEventHandler> Combine(IEventEntry<TEventHandler> entry);
		ITweakedEvent<TEventHandler> Subtract(IEventEntry<TEventHandler> entry);
	}

	public interface IEventEntry : IEquatable<IEventEntry>, IDisposable
	{
		/// <summary>Invoke the entry and returns the value of IsDisposed</summary>
		bool Invoke(object sender, EventArgs e);
		bool IsDisposed { get; }
	}

	public interface IEventEntry<TEventHandler> : IEventEntry where TEventHandler : class
	{
		/// <summary>Compares this IEventEntry with a delegate for equality</summary>
		/// <param name="handler">A delegate to be compared with</param>
		/// <returns>True if this IEventEntry is equivalent to the handler</returns>
		bool EqualsHandler(TEventHandler handler);
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer (Senior) ThoughtWorks
Brazil Brazil
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions