xiaoguozi's Blog
Pay it forword - 我并不觉的自豪,我所尝试的事情都失败了······习惯原本生活的人不容易改变,就算现状很糟,他们也很难改变,在过程中,他们还是放弃了······他们一放弃,大家就都是输家······让爱传出去,很困难,也无法预料,人们需要更细心的观察别人,要随时注意才能保护别人,因为他们未必知道自己要什么·····
CLR事件机制建立在委托机制上
class MailManager
    {
        
public class MailEventArgs : EventArgs
        {
            
public MailEventArgs(
                String from,
                String to,
                String subject,
                String body)
            {
                
this.from = from;
                
this.to = to;
                
this.subject = subject;
                
this.body = body;
            }
            
public readonly String from, to, subject, body;
        }
        
public delegate void MailEventHandler(Object sender, MailEventArgs e);
        
public event MailEventHandler MailMsg;
        
protected virtual void OnMailMsg(MailEventArgs e)
        {
            
if (MailMsg != null)
            {
                MailMsg(
this, e);
            }
        }
        
public virtual void SimulateArrivingMsg(String from, String to, String subject, String body)
        {
            MailEventArgs e 
= new MailEventArgs(from, to, subject, body);
            OnMailMsg(e);
        }
    }
以上是一个事件类型定义,简单步骤:
1.定义一个类型,保存所有传递参数。
.net框架规定所有的信息类型继承于EventArgs,类型名称以EventArgs结束,EventArgs原型如下:
[Serializable]
public class EventArgs
{
    public static readonly EventArgs Empty = new EventArgs();
    public EventArgs(){};
}
只有一个静态的Empty成员,因为事件中有些不需要额外的参数信息,所以只要提供EventArgs.Empty,不需要在构造新的对象
2.定义一个委托类型,指定事件触发时调用的函数原型
public delegate void MailEventHandler(Object sender, MailEventArgs e);
如果事件中并没有额外的传递信息,则可以使用System.EventHandler,原型为
public delegate void EventHandler(Object sender,EventArgs e);
3.定义一个事件成员
public event MailEventHandler MailMsg;
4.定义受保护的虚方法,通知事件登记对象
protected virtual void OnMailMsg(MailEventArgs e);
5.定义驱动事件方法
public virtual void SimulateArrivingMsg(String from, String to, String subject, String body);

深入理解事件
当编译器遇到
public event MailEventHandler MailMsg;
会产生3个构造,一个私有委托类型,及add和remove方法
private MailEventHandler MailMsg;
[MethodImplAttribute(MethodImplOptions.Synchronized)]
public virtual void add_MailMsg(MailEventHandler handler)
{
     MailMsg = (MailEventHandler)Delegate.Combine(MailMsg, handler);
}
[MethodImplAttribute(MethodImplOptions.Synchronized)]
public virtual void remove_MailMsg(MailEventHandler handler)
{
     MailMsg = (MailEventHandler)Delegate.Remove(MailMsg, handler);
}
通过MailMsg内_prev字段可以将添加的注册对象保存

侦听事件
class Fax
    {
        public Fax(MailManager mm)
        {
            mm.MailMsg += new MailManager.MailEventHandler(FaxMsg);
        }
        private void FaxMsg(Object sender, MailManager.MailEventArgs e)
        {

        }
        public void UnRegister(MailManager mm)
        {
            MailManager.MailEventHandler callback = new MailManager.MailEventHandler(FaxMsg);
            mm.MailMsg -= callback;
        }
    }

注意,当一个对象仍然登记有另外一个对象的事件,该对象就不可能对垃圾回收,如果我们类实现了IDisposable接口,那我们应该在
Dispose理注销所有登记事件

显示控制事件注册
private MailEventHandler mailMsgEventHandlerDelegate;
        public event MailEventHandler MailMsg
        {
            add
            {
                mailMsgEventHandlerDelegate =(MailEventHandler)Delegate.Combine(mailMsgEventHandlerDelegate, value);
            }
            remove
            {
                mailMsgEventHandlerDelegate = (MailEventHandler)Delegate.Remove(mailMsgEventHandlerDelegate, value);
            }
        }
        protected virtual void OnMailMsg(MailEventArgs e)
        {
            if (MailMsg != null)
            {
                mailMsgEventHandlerDelegate(this, e);
            }
        }

来代替
public event MailEventHandler MailMsg;定义

当一个类型中含有多个事件时,由于每个事件事例声明都将产生委托字段,所以推荐
不要提供公共的事件成员变量,使用事件访问器替换这些变量

class EventHandlerSet:IDisposable
    {
        private Hashtable events = new Hashtable();
        public virtual Delegate this[Object eventKey]
        {
            get
            {
                return (Delegate)events[eventKey];
            }
            set
            {
                events[eventKey] = value;
            }
        }
        public virtual void AddHandler(Object eventKey,Delegate handler)
        {
            events[eventKey] = Delegate.Combine((Delegate)events[eventKey], handler);
        }
        public virtual void RevHandler(Object eventKey, Delegate handler)
        {
            events[eventKey] = Delegate.Remove((Delegate)events[eventKey], handler);
        }
        public virtual void Fire(Object eventKey, Object sender, EventArgs e)
        {
            Delegate d = (Delegate)events[eventKey];
            if (d != null)
                d.DynamicInvoke(new Object[]{sender,e});
        }
        public void Dispose()
        {
            events = null;
        }
        public static EventHandlerSet Synchronized(EventHandlerSet eventHandlerSet)
        {
            if (eventHandlerSet == null)
                throw new ArgumentNullException("eventHandlerSet");
            return new SynchronizedEventHandlerSet(eventHandlerSet);
        }
        public class SynchronizedEventHandlerSet : EventHandlerSet
        {
            private EventHandlerSet eventHandlerSet;
            public SynchronizedEventHandlerSet(EventHandlerSet eventHandlerSet)
            {
                this.eventHandlerSet = eventHandlerSet;
                Dispose();
            }
            public override Delegate this[object eventKey]
            {
                [MethodImpl(MethodImplOptions.Synchronized)]
                get
                {
                    return eventHandlerSet[eventKey];
                }
                set
                {
                    eventHandlerSet[eventKey] = value;
                }
            }
            [MethodImpl(MethodImplOptions.Synchronized)]
            public override void AddHandler(object eventKey, Delegate handler)
            {
                eventHandlerSet.AddHandler(eventKey, handler);
            }
            [MethodImpl(MethodImplOptions.Synchronized)]
            public override void RevHandler(object eventKey, Delegate handler)
            {
                eventHandlerSet.RevHandler(eventKey, handler);
            }
            [MethodImpl(MethodImplOptions.Synchronized)]
            public override void Fire(object eventKey, object sender, EventArgs e)
            {
                eventHandlerSet.Fire(eventKey, sender, e);
            }
        }
    }
    class TypeWithLotsEvents
    {
        protected EventHandlerSet eventSet = EventHandlerSet.Synchronized(new EventHandlerSet());
        protected static readonly Object fooEventKey = new Object();
        public class FooEventArgs : EventArgs { };
        public delegate void FooEventHandler(Object sender, FooEventArgs e);
        public event FooEventHandler Foo
        {
            add
            {
                eventSet.AddHandler(fooEventKey, value);
            }
            remove
            {
                eventSet.AddHandler(fooEventKey, value);
            }
        }
        protected virtual void OnFoo(FooEventArgs e)
        {
            eventSet.Fire(fooEventKey, this, e);
        }
        public void SimulateFoo()
        {
            OnFoo(new FooEventArgs());
        }

    }
以上是microsoft .net 框架设计一个example,如果设计该种事件类型,其中给出了EventHandlerSet的实现,
.net框架中也有类似的事件 EventHandlerList,但是访问效率和线程同步有缺陷,所以有需要我们自己提供
EventHandlerSet实现.详情请参考microsoft .net 框架设计

posted on 2010-09-30 14:17 小果子 阅读(400) 评论(0)  编辑 收藏 引用 所属分类: .Net

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理