zoukankan      html  css  js  c++  java
  • C# 中多事件类型

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    namespace NET.MST.Sixth.MultiEventsClass
    {
        class MainClass
        {
            static void Main(string[] args)
            {
                //测试事件的触发
                using (MultiEventsClass c = new MultiEventsClass())
                {
                    Customer customer = new Customer(c);
                    c.RiseEvent1();
                    c.RiseEvent2();
                }
                Console.Read();
            }
        }

        /// <summary>
        /// 多事件类型
        /// </summary>
        public partial class MultiEventsClass:IDisposable
        {
            /// <summary>
            /// System.ComponentModel.EventHandlerList包含了一个委托链表的容器
            /// 实现了多事件存放在一个容器之中的包装
            /// EventHandlerList使用的是链表数据结构
            /// </summary>
            private EventHandlerList _events;
           
            //公共构造方法
            public MultiEventsClass()
            {
                _events = new EventHandlerList();
            }
            /// <summary>
            /// 释放EventHanlderList
            /// </summary>
            public void Dispose()
            {
                _events.Dispose();
            }
        }
        /// <summary>
        /// 多事件类型
        /// </summary>
        public partial class MultiEventsClass : IDisposable
        {
            //下面为每一个需要实现的事件申明委托类型、订阅和取消定语方法、事件在集合中的键和触发事件方法
            //这样的定义和实际申明一个事件成员不同,这样做不会在一个新的MultiEventsClass中分配所有的事件委托链表的内存空间
            //这就是提高性能的关键
            //申明事件1
            #region event1
            //事件1的委托原型
            public delegate void Event1Handler(Object sender, EventArgs e);
            //这里是静态的字段,有效提高性能
            protected static readonly Object Event1Key = new object();       
            /// <summary>
            /// 一组订阅、取消订阅事件的方法
            /// 注意EventHandlerList并不提供线程同步,所以在add和remove方法前加上线程同步属性
            /// 读者可以采取lock机制来代替
            /// </summary>
            public event Event1Handler Event1
            {
                [MethodImpl(MethodImplOptions.Synchronized)]
                add
                {
                    _events.AddHandler(Event1Key, value);
                }
                [MethodImpl(MethodImplOptions.Synchronized)]
                remove
                {
                    _events.RemoveHandler(Event1Key, value);
                }
            }
            /// <summary>
            /// 触发事件1
            /// </summary>
            /// <param name="e"></param>
            protected virtual void OnEvent1(EventArgs e)
            {
                _events[Event1Key].DynamicInvoke(this, e);
            }
            /// <summary>
            /// 这个方法简单地触发事件1,以便于测试
            /// </summary>
            public void RiseEvent1()
            {
                OnEvent1(EventArgs.Empty);
            }
            #endregion
            //申明事件2
            #region event2
            //事件2的委托原型
            public delegate void Event2Handler(Object sender, EventArgs e);
            //这里是静态的字段,有效提高性能
            protected static readonly Object Event2Key = new object();
            /// <summary>
            /// 一组订阅、取消订阅事件的方法
            /// 注意EventHandlerList并不提供线程同步,所以在add和remove方法前加上线程同步属性
            /// 读者可以采取lock机制来代替
            /// </summary>
            public event Event2Handler Event2
            {
                [MethodImpl(MethodImplOptions.Synchronized)]
                add
                {
                    _events.AddHandler(Event2Key, value);
                }
                [MethodImpl(MethodImplOptions.Synchronized)]
                remove
                {
                    _events.RemoveHandler(Event2Key, value);
                }
            }
            /// <summary>
            /// 触发事件2
            /// </summary>
            /// <param name="e"></param>
            protected virtual void OnEvent2(EventArgs e)
            {
                _events[Event2Key].DynamicInvoke(this, e);
            }
            /// <summary>
            /// 这个方法简单地触发事件2,以便于测试
            /// </summary>
            public void RiseEvent2()
            {
                OnEvent2(EventArgs.Empty);
            }
            #endregion    
        }

        /// <summary>
        /// 构造一个订阅事件的类型
        /// </summary>
        public class Customer
        {
            public Customer(MultiEventsClass events)
            {
                //订阅事件1
                events.Event1 += Event1Handler;
                //订阅事件2
                events.Event2 += Event2Handler;
            }
            /// <summary>
            /// 事件1回调方法
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="args"></param>
            private void Event1Handler(object sender, EventArgs args)
            {
                Console.WriteLine("事件1触发");
            }
            /// <summary>
            /// 事件2回调方法
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="args"></param>
            private void Event2Handler(object sender, EventArgs args)
            {
                Console.WriteLine("事件2触发");
            }
        }
    }

  • 相关阅读:
    数据挖掘、数据分析的书籍推荐
    跳槽时间如何选择
    求职网站总结
    Eclipse中Applet程序运行时Applet小程序大小的设置
    统计学习导论:基于R应用——第五章习题
    统计学习导论:基于R应用——第四章习题
    统计学习导论:基于R应用——第三章习题
    Windows环境下安装IPython NoteBook
    centos7上mysql无法启动也没有日志
    CentOS 6.4下Squid代理服务器的安装与配置
  • 原文地址:https://www.cnblogs.com/jasonjiang/p/1763875.html
Copyright © 2011-2022 走看看