C# 事件参数库






3.20/5 (9投票s)
一个包含常用事件参数类的库。
引言
有很多种你经常需要的事件参数,例如 CancelEventArgs
。这个库包含了一系列事件参数。
背景
接口
我将事件参数的不同能力放入了以下接口中
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; } }
interface IRangeEventArgs : IIndexEventArgs { int Count { get; } }
这些接口允许你使用一个处理程序函数轻松处理多个事件。
ICancelEventArgs
包含两个成员(bool IsCanceled { get; }
, void Cancel();
)以防止事件处理程序通过类似以下的代码将 Canceled
属性设置为 false
e.Canceled = !condition;
类
然后,我在类中实现了这些接口的组合
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
class RangeEventArgs : IRangeEventArgs
class RangeCancelEventArgs : IRangeEventArgs, ICancelEventArgs
在实践中,这些类相互派生,以编写更少的代码。
委托(Delegates)
该库包含以下事件处理程序委托
public delegate void EventHandler<TEventArgs, TSender>(TEventArgs e, TSender sender)
where TEventArgs : EventArgs;
这个处理程序允许你使用第二个泛型参数指定发送者的类型。
使用代码
作为一个例子,我开发了一个提供以下事件的通知列表
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;
我实现了 IList<T>
、ICollection<T>
和 IEnumerable<T>
以提供基本列表功能。内部使用 List<T>
。
事件触发
作为一个事件触发的例子,我将向你展示 Insert
函数
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);
}
}
如你所见,事件触发封装在一个 protected
函数中,该函数实例化事件参数类,如果事件处理程序没有取消该操作,则返回 true
。
事件处理
作为一个事件处理的例子,我将向你展示如何防止所提到的 NotifyList
以任何方式更改
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();
}
如你所见,所有事件只有一个处理程序。这是因为库提供的接口所致。
历史
- 星期日 3 月 9日:创建文章。
- 星期一 3 月 10日:添加示例;更正了
ValueIndexCancelEventArgs<T>
类中的错误实现。 - 星期三 3 月 12日:添加了
IRangeEventArgs
接口。