C#多播委托和事件event,它们区别,事件引用之管道设计模式整理总结

本文一共分为三个部分:多播委托知识点,多播委托和事件区别,事件应用之管道设计

第一:多播委托的知识点:

A:任何一个委托实例,实际上都是多播委托,即可以+=,也可以-=不过需要注意一点

只有相同对象的相同方法才可以移除,比如相同的静态方法等

B:多播委托,赋值多个方法时,不能异步调用,报错,如果一定需要,可以依次遍历出每个多播委托中的方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DelegateEventDemo
{
    public delegate void TestDelegate();
    class Program
    {
        
        static void Main(string[] args)
        {

            new Program().Demo();
        }
        public static void Test() {
            Console.WriteLine("我是静态static方法");
        }
        public void Test2()
        {
            Console.WriteLine("我是类中普通方法");
        }

        private void Demo() {
            //第一种:lambda
            TestDelegate testDelegate = new TestDelegate(() => {
                Console.WriteLine("我是lambda");
            });
            //第二种:静态方法
            testDelegate += new TestDelegate(Test);
            //第三种:自己类中方法
            testDelegate += new TestDelegate(this.Test2);
            //第四种:其他类普通方法,
            testDelegate += new TestDelegate(new OtherClass().Test2);
            //第五种:其他类静态方法
            testDelegate += new TestDelegate(OtherClass.Test);

            //第一种:lambda,其实是另一个方法,没能取消
            testDelegate -= new TestDelegate(() => {
            });
            //第二种:静态方法,相同的那个方法,能取消
            testDelegate -= new TestDelegate(Test);
            //第三种:自己类中相同那个静态方法,能取消
            testDelegate -= new TestDelegate(this.Test2);
            //第四种:其他类普通方法,另一个实例中方法,不能取消
            testDelegate -= new TestDelegate(new OtherClass().Test2);
            //第五种:其他类静态方法,能取消
            testDelegate -= new TestDelegate(OtherClass.Test);

            //testDelegate.Invoke();

            //testDelegate.BeginInvoke()

            //只能移除完全相同的方法,所属对象和方法签名本身
            //一个委托实例,包括多个方法,就是多播委托,

            //后面两个参数是回调,和参数,
            //提示该委托,必须只有一个方法目标,既只能有一个方法
            //testDelegate.BeginInvoke(null, null);
            foreach (TestDelegate item in testDelegate.GetInvocationList())
            {
                item.BeginInvoke(null,null);
            }
        }
    }

    class OtherClass{
        public static void Test()
        {
            Console.WriteLine("我是其他类静态static方法");
        }
        public void Test2()
        {
            Console.WriteLine("我是其他类中普通方法");
        }
    }


}

第二个知识点:多播委托和事件区别

委托其实是一个类,继承自多播委托的类

它事件,本来就是一个委托的实例,加上event关键字,所以他不是类型,
事件和一般委托实例区别,事件不能在非所属对象中,进行调用,等等,进行一些列安全限制
事件他在外面只能是+=,-=

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EventAndMutityCastDelegate
{
    public delegate void HandlerCat();

    class Program
    {
        static void Main(string[] args)
        {
            //多播委托,就像一个容器,可以放一定标准的方法,(某种签名的方法),
            //为什么需要委托呢?凌晨醒来,忽然意识到一个问题,假定如下场景,猫叫引起一系列对象连锁的反应
            // 猫叫,
            //老鼠跑,狗也叫,小孩哭,父亲咆哮,母亲安抚,哥哥翻身,
           
            new Cat().Miao();
            //这里猫叫,触发一系列对象动作,想起委托的作用,就是封装一些列动作,
            //这里猫叫,即调用多播委托即可,同时想到事件的原理,正是点击触发,引起连锁反应
            ///有个严重的问题,依赖多,追求开闭原则,扩展开放,修改关闭,
            ///不同对象,稍稍修改,换个调用顺序都要修改cat对象,
            ///
            //!!!!!!!!!!!!!!!!就算把事件,多播委托拿进来,仍然是放在miao方法里面,尽量不改动miao方法!!!!!!!!!!!!!!
            {
                Cat delegatecat = new Cat();
                delegatecat.handler += new HandlerCat(new Mouse().Run);
                delegatecat.handler += new HandlerCat(new Dog().Scream);
                delegatecat.handler += new HandlerCat(new Baby().Cry);
                delegatecat.handler.Invoke();
                delegatecat.handler = null;
                delegatecat.handler += new HandlerCat(new Father().Angry);
                delegatecat.handler += new HandlerCat(new Mouther().Love);
                delegatecat.handler += new HandlerCat(new Brother().Wrap);
                //
                delegatecat.MiaoDelegate();
            }

             {
                Cat delegatecat = new Cat();
                delegatecat.EventHandlerCat += new HandlerCat(new Mouse().Run);
                delegatecat.EventHandlerCat += new HandlerCat(new Dog().Scream);
                delegatecat.EventHandlerCat += new HandlerCat(new Baby().Cry);

                //参数不同,可以通过lambda封装一下再次调用,非常灵活
                delegatecat.EventHandlerCat += () =>
                {
                    new NewMethod().Test(3);
                };
                //委托其实是一个类,继承自多播委托的类
                //事件和一般委托实例区别,事件不能在非所属对象中,进行调用,等等,进行一些列安全限制
                //他在外面只能是+=,-=
                //delegatecat.EventHandlerCathandler.Invoke();
                //delegatecat.EventHandlerCat = null;
                delegatecat.EventHandlerCat += new HandlerCat(new Father().Angry);
                delegatecat.EventHandlerCat += new HandlerCat(new Mouther().Love);
                delegatecat.EventHandlerCat += new HandlerCat(new Brother().Wrap);
                //
                delegatecat.MiaoEvent();
            }
           
           
    }
    }
    class NewMethod
    {
        public void Test(int count)
        {
            Console.WriteLine("叫三声");
        }
    }
    class Cat {
        //灵活运用,没有参数返回,不就是Action委托么?
        
        public HandlerCat handler;
        public event HandlerCat EventHandlerCat;

        public void Miao() {
            Console.WriteLine("我是猫叫");
            new Mouse().Run();
            new Dog().Scream();
            new Baby().Cry();
            new Father().Angry();
            new Mouther().Love();
            new Brother().Wrap();
            //..
            //万一有,不同参数的方法,怎么办?
            new NewMethod().Test(3);
        }

       
        //
        public void MiaoDelegate() {
            Console.WriteLine("我是猫叫");
            if (handler!=null)
            {
                handler.Invoke();
            }   
            //hander.Invoke();
            //new Mouse().Run();
            //new Dog().Scream();
        }
        //EentHandlerCat eventhandlerCat 不能把事件当成类型传递
        public void MiaoEvent()
        {
            Console.WriteLine("我是event猫叫");
            //它事件,本来就是一个委托的实例,加上event关键字,所以他不是类型,不能也无须再次做如下声明
            //调用是这个实例,可以+=,或是-=,相比较多播委托,它限制
            //EventHandlerCat eventhandler = new HandlerCat(new Mouse().Run);
            //this.EventHandlerCat = new HandlerCat(new Mouse().Run);
            //this.EventHandlerCat += new HandlerCat(new Dog().Scream);
            //this.EventHandlerCat += new HandlerCat(new Baby().Cry);
            hander.Invoke();
            hander = null;
            //this.EventHandlerCat += new HandlerCat(new Father().Angry);
            //this.EventHandlerCat += new HandlerCat(new Mouther().Love);
            //this.EventHandlerCat += new HandlerCat(new Brother().Wrap);
            //EventHandlerCat.Invoke();
            //new Mouse().Run();
            //new Dog().Scream();
            if (EventHandlerCat!=null)
            {
                EventHandlerCat.Invoke();
            }
        }
    }
    class Mouse {
        public void Run() {
            Console.WriteLine("Mouse Run");
        }
    }

    class Dog
    {
        public void Scream()
        {
            Console.WriteLine("Dog Scream");
        }
    }

    class Baby
    {
        public void Cry()
        {
            Console.WriteLine("Baby Cry");
        }
    }

    class Father
    {
        public void Angry()
        {
            Console.WriteLine("Father Angry");
        }
    }

    class Mouther
    {
        public void Love()
        {
            Console.WriteLine("Mouther Love");
        }
    }

    class Brother
    {
        public void Wrap()
        {
            Console.WriteLine("Brother Wrap");
        }
    }
}

第三个知识点:

事件的应用之管道设计模式,我们程序设计遵循的非常重要的一个模式是,开闭原则,即对修改关闭,对扩展开放,

这里封装固定的逻辑,借助事件可提供一个对外扩展接口, 事件可简单理解是方法的一个容器集合,事实上,整个ASP.NET架构,都是基于这种管道设计模式,处理一个请求,封装固定的cookie,session返回页面html,同时提供很多事件,用来给开发者调用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EventHttpHandler
{
    class Program
    {
        //事件的实际应用,相关设计,管道处理模式
        static void Main(string[] args)
        {
            //事件就是一种特殊的委托实例,可以直接添加方法,进行封装,粗浅地理解为方法容器
            //比如吃大排档的过程,分为五步,固定,现在增加一个个性需求,吃饭之前洗脸,或是运动完睡觉等等需求
            //传统做法,就是继续添加这些动作,到Eat方法,
            //更好的设计,是提示提供一个事件即,方法容器判断不为空执行,从而不改变吃方法,只在外面添加方法到里面去即可
            //

            PipeDemo pipedemo = new PipeDemo();
            pipedemo.MenuBefor += () => {
                Console.WriteLine("吃饭之前洗脸");
            };
            pipedemo.SportAfter += () => {
                Console.WriteLine("运动之后睡觉");
            };
            pipedemo.Eat();
            //Action<int> action1

            //分析总结,利用事件实现管道模式的好处,方便扩展,
            //扩展一下,实际上整个Asp.Net框架,就是基于事件驱动的架构
            /*
             整个框架中对网页端来的请求HttpHandler,除了生成html,还有很多事情要做,
             cookie,session 安全检验,实际上差不多有25个事件,常用的是19个,
             框架就是将固定的逻辑封装好,其他额外要处理的事件,通过事件设计成管道模式
             提供一个扩展接口,给外面调用
             */
        }
    }

    class PipeDemo {
        public event Action MenuBefor;
        public event Action DrinkEatingBefor;    
        public event Action PostEatingBefor;
        public event Action ToothBefor;
        public event Action SportBefor;

        public event Action MenuAfter;
        public event Action DrinkEatingAfter;
        public event Action PostEatingAfter;
        public event Action ToothAfter;
        public event Action SportAfter;
        public void Eat() {
            if (MenuBefor!=null)
            {
                MenuBefor.Invoke();
            }
            Console.WriteLine("点餐");
            if (MenuAfter != null)
            {
                MenuAfter.Invoke();
            }
            Console.WriteLine("上菜");
            Console.WriteLine("喝酒吃菜");
            Console.WriteLine("剔牙");
            if (SportBefor!=null)
            {
                SportBefor.Invoke();
            }
            Console.WriteLine("运动");
            if (SportAfter!=null)
            {
                SportAfter.Invoke();
            }
        }
    }
}

参考朝夕教育Eleven老师课堂讲解

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值