Introduce DataBase,Asp.net,JavaScript,Xml,Html,Css,Sql,Php,ASP.NET Controls,AJAX,Tools,HTML,CSS,JavaScript,Open Source Project,WPF,.Net Framework,Linq
Top Recommended Hosting

C# Event arguments library

by the3factory 3/10/2008 6:20:00 PM
 

Background

Interfaces

I've put the different abilities of the event arguments into the following interfaces:

interface IValueEventArgs<T> { T Value { get; } }
interface ICancelEventArgs { bool IsCanceled { get; } void Cancel(); }
interface INewValueEventArgs<T> { T NewValue { get; set; } }
interface IOldValueEventArgs<T> { T OldValue { get; } }
interface IIndexEventArgs { int Index { get; } }

These interfaces allow you to easily handle multiple events in one handler function.

The ICancelEventArgs contains two members (bool IsCanceled { get; } void Cancel();) to prevent event handlers from setting the Canceled property to false by using code like this:

e.Canceled = !condition;

Classes

Then I implemented some combinations of these interfaces in classes:

class ValueEventArgs<T> : IValueEventArgs<T>
class CancelEventArgs : ICancelEventArgs
class ValueCancelEventArgs<T> : IValueEventArgs<T>, ICancelEventArgs
class ValueChangingEventArgs<T> : IValueEventArgs<T>,  INewValueEventArgs<T>
class ValueChangedEventArgs<T> : IValueEventArgs<T>,  IOldValueEventArgs<T>
class ValueIndexEventArgs<T> : IValueEventArgs<T>,  IIndexEventArgs
class ValueIndexChangingEventArgs<T> : IValueEventArgs<T>,  INewValueEventArgs<T>, IIndexEventArgs
class ValueIndexChangedEventArgs<T> : IValueEventArgs<T>,  IOldValueEventArgs<T>, IIndexEventArgs

In practice, these classes are derived from each other to write less code.

Delegates

Then, the library contains the following event handler delegate:

public delegate void EventHandler<TEventArgs, TSender>(TEventArgs e, TSender sender)
where TEventArgs : EventArgs;

This handler allows you to specify the sender's type with the second generic parameter.

Using the code

As an example, i have developed a notify list that provides the following events:

public event EventHandler<ValueIndexCancelEventArgs<T>, NotifyList<T>> Inserting;
public event EventHandler<ValueIndexEventArgs<T>, NotifyList<T>> Inserted;
public event EventHandler<ValueIndexChangingEventArgs<T>, NotifyList<T>> Setting;
public event EventHandler<ValueIndexChangedEventArgs<T>, NotifyList<T>> Set;
public event EventHandler<ValueIndexCancelEventArgs<T>, NotifyList<T>> Removing;
public event EventHandler<ValueIndexEventArgs<T>, NotifyList<T>> Removed;
public event EventHandler<CancelEventArgs, NotifyList<T>> Clearing;
public event EventHandler<EventArgs, NotifyList<T>> Cleared; 

I implemented IList<T>, ICollection<T> and IEnumerable<T> to provide basic list functionality. Internal, a List<T> is used.

Event raising

As an example for event raising I'll show you the Insert function:

Collapse
public void Insert(int index, T item)
{
if (this.OnInserting(item, index))
{
this.list.Insert(index, item);
this.OnInserted(item, index);
}
}
protected bool OnInserting(T item, int index)
{
if (this.Inserting != null)
{
ValueIndexCancelEventArgs<T> evArgs = new ValueIndexCancelEventArgs<T>(item, index);
this.Inserting(this, evArgs);
return !evArgs.IsCanceled;
}
else
return true;
}
protected void OnInserted(T item, int index)
{
if (this.Inserted != null)
{
ValueIndexEventArgs<T> eventArgs = new ValueIndexEventArgs<T>(item, index);
this.Inserted(this, eventArgs);
}
}

As you can see, the event raising is encapsulated in a protected function, that instances the event argument class and returns true if the action has not been canceled by an event handler.

Event handling

As an event handling example I'll show you how to prevent the mentioned NotifyList from changing in any way:

Collapse
static void Main(string[] args)
{
NotifyList<string> myLst = new NotifyList<string>();
myLst.Add("test");
myLst.Add("qwert");
myLst.Inserting += new EventHandler<ValueIndexCancelEventArgs<string>, NotifyList<string>>(myLst_Changing);
myLst.Setting += new EventHandler<ValueIndexChangingEventArgs<string>, NotifyList<string>>(myLst_Changing);
myLst.Removing += new EventHandler<ValueIndexCancelEventArgs<string>, NotifyList<string>>(myLst_Changing);
myLst.Clearing += new EventHandler<CancelEventArgs, NotifyList<string>>(myLst_Changing);
myLst.Clear();
myLst.Add("hello world");
myLst.Add("test123");
myLst.RemoveAt(0);
myLst.Insert(1, "hello universe");
foreach (string itm in myLst)
Console.WriteLine(itm);
//Output:
//test
//qwert
Console.ReadLine();
}
static void myLst_Changing(NotifyList<string> sender, ICancelEventArgs e)
{
e.Cancel();
}

As you can see, there is only one handler for all events. This is possible because of the interfaces provided by the library.

Tags:

C#

Related posts

Sign up for PayPal and start accepting credit card payments instantly.


Powered by BlogEngine.NET 1.2.0.0