委托

SunnyFan大约 13 分钟约 3826 字

委托

什么是委托,委托的本质是什么?

{
    /// <summary>
    /// 1.无参数无返回值委托
    /// </summary>
    public delegate void NoReturnNoParaOutClass();
    public class CustomDelegate //: MulticastDelegate
    {
        /// <summary>
        /// 2.无参数无返回值委托
        /// </summary>
        public delegate void NoReturnNoPara();
        /// <summary>
        /// 3.有参数无返回值委托
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public delegate void NoReturnWithPara(int x, int y);
        /// <summary>
        /// 4.无参数有返回值的委托
        /// </summary>
        /// <returns></returns>
        public delegate int WithReturnNoPara();
        /// <summary>
        /// 5.带参数,带返回值的委托
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public delegate int WithReturnWithPara(out int x, ref int y);

        public static void Show()
        {
            NoReturnNoParaOutClass noReturnNoParaOutClass = new NoReturnNoParaOutClass(NoReturnNoParaMehtod);

            //NoReturnNoParaOutClass noReturnNoParaOutClass1 = new NoReturnNoParaOutClass(NoReturnWithParaMehtod);
            //NoReturnNoPara noReturnNoPara = new NoReturnNoPara(NoReturnWithParaMehtod);
            //NoReturnWithPara noReturnWithPara = new NoReturnWithPara(NoReturnNoParaMehtod);
            NoReturnWithPara noReturnWithPara1 = new NoReturnWithPara(NoReturnWithParaMehtod);
            //noReturnWithPara1.Invoke()
            //WithReturnNoPara withReturnNoPara = new WithReturnNoPara(WithReturnNoParaMehtod);

             WithReturnNoPara withReturnNoPara = WithReturnNoParaMehtod; //这样写也没有问题---委托的实例--可以直接指向一个和这个委托参数+返回值完全匹配的方法;--语法糖--编译器给我们提供额便捷功能--new WithReturnNoPara();省略掉了

            int iResult = withReturnNoPara.Invoke();//如果委托定义没有参数;在Inovke也没有参数 
            //withReturnNoPara.BeginInvoke(null, null);//开启一个新的线程去执行委托
            //withReturnNoPara.EndInvoke()//回调

            NoReturnWithPara noReturnWithPara2 = NoReturnWithParaMehtod;
            NoReturnWithPara noReturnWithPara3 = (x, y) => { };
        }

        private static void NoReturnNoParaMehtod()
        {
            Console.WriteLine("这是一个无参数无返回值的方法。。。");
        }

        private static void NoReturnWithParaMehtod(int x, int y)
        {
            Console.WriteLine($"这是一个带参数无返回值的方法。。。");
        }

        private static int WithReturnNoParaMehtod()
        {
            Console.WriteLine($"这是一个无参数带返回值的方法。。。");
            return default(int);
        }

        private static int WithReturnWithParaMehtod(out int x, ref int y)
        {
            Console.WriteLine($"这是一个带参数无返回值的方法。。。");
            x = 1;
            return default(int);
        }
    }

    public class OtherClass
    {
        public void DoNothing()
        {
            Console.WriteLine("This is DoNothing");
        }
        public static void DoNothingStatic()
        {
            Console.WriteLine("This is DoNothingStatic");
        }
    }
}    

委托的实例化,执行委托

委托的作用和意义

 {
    Student student = new Student()
    {
        Id = 1234,
        Name = "慎独",
        Age = 25,
        ClassId = 1
    };
    student.SayHi();
    //场景1.学生分类?  武汉人、上海人、广东人--三种不同类型的人;问候的口语不一样;
    //方案1:定义枚举,通过枚举判断,分贝给出不同的问候方式;
    //方案2:根据不同的类型的人,分别定义不同的方法,来实现问候方式
    {
        //1.:武汉  2.上海  3.广东
        student.SayHi(UserType.Wuhan);//
        student.SayHi(UserType.Shanghai);
        student.SayHi(UserType.GuangDong);
    }
    {
        student.SayHiWuhHan();
        student.SayHiShangHai();
        student.SayHiGuangDong();
    }
    //三-一、如果增加一个类型的人 
    //方案1:多种分支判断    ---如果增加一个类型的人------增加一个Beijing人;---早上好!
    //    问题:SayHi方法不稳定,一旦增加一个类型的人;SayHi方法就需要修改;方法的所有逻辑都选哟重新测试. 一个方法中有多种业务逻辑---业务逻辑耦合
    //方案2:每个方法都式独立的:
    //    问题:---如果增加一个类型的人---增加一个方法;功能独立,对其他的功能内部不影响;
    //完美实现:优势----有让马儿跑,又让马尔不吃---牛逼!
    //从上而下:
    //好处;    1.代码稳定,SayHiperfect方法稳定,不需要修改:2.执行的逻辑不在同一个方法中,---逻辑解耦 
    //从下而上:1.去掉重复代码,逻辑重用
    //三-二:如果需要增加一个功能的业务逻辑呢?--问候前-手举起来,招招手~~
    //方案1:增加功能的业务逻辑很方便;
    //方案2:增加公共逻辑--每个方法都选哟增加--增加的代码都是一样的,----大量的重复代码; 
    //两种方案相比较,各有千秋,各有优劣;
    //这两种都有不完美的地方----有没有既可以没有那么多的重复代码,也相对稳定的方案呢?--有
    //SayHiPerfect---
    //传递枚举的时候:目的是为了选择不同的业务逻辑:既然最终都是要选择业务逻辑的;--就可以传递逻辑呗;逻辑是什么--逻辑其实就行为---行为就是方法---方法的传递;就需要把方法当做参数一样传递过来;--委托在实例化的时候,委托就要一个方法;就可以传递一个委托,把方法放在委托中传递过来; 
    {
        ///武汉人问候
        SayHiDalegate sayHiDalegate = new SayHiDalegate(student.SayHiWuhHan);
        student.SayHiperfect(sayHiDalegate);
        SayHiDalegate sayHiDalegate1 = new SayHiDalegate(student.SayHiShangHai);
        student.SayHiperfect(sayHiDalegate1);
        SayHiDalegate sayHiDalegate2 = new SayHiDalegate(student.SayHiGuangDong);
        student.SayHiperfect(sayHiDalegate2);
        SayHiDalegate sayHiDalegate3 = new SayHiDalegate(student.SayHiBeijing);
        student.SayHiperfect(sayHiDalegate2);
    } 
    //三--建议:
    //问题:什么情况下?可以考虑使用委托?
    //1.方法内部业务逻辑耦合严重---考虑使用委托
    //2.如果多个方法,有很多重复代码---去掉重复代码--逻辑重用---考虑使用委托 
}
{
    /// <summary>
    /// 学生类
    /// </summary>
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int ClassId { get; set; }
        public int Age { get; set; }

        /// <summary>
        /// 问好
        /// </summary>
        public void SayHi(UserType type)
        {
            Console.WriteLine("问候前。。。招招手。。。");
            switch (type)
            {
                case UserType.Wuhan:
                    Console.WriteLine("吃了么?过早了吗?");
                    break;
                case UserType.Shanghai:
                    Console.WriteLine("侬好!");
                    break;
                case UserType.GuangDong:
                    Console.WriteLine("雷猴!");
                    break;
                default:
                    throw new Exception("NO UserType"); //不掩盖错误

            }
            Console.WriteLine("你好!");
        }

        public void SayHiWuhHan()
        { 
            Console.WriteLine("吃了么?过早了吗?");
        }

        public void SayHiShangHai()
        { 
            Console.WriteLine("侬好!");
        }

        public void SayHiGuangDong()
        { 
            Console.WriteLine("雷猴!");
        }

        public void SayHiBeijing()
        { 
            Console.WriteLine("早上好!");
        }

        /// <summary>
        /// 既没有重复代码-0-也相对稳定的方法---完美方法;
        /// </summary>
        public void SayHiperfect(SayHiDalegate sayHiDalegate)
        {
            Console.WriteLine("问候前,招招手。。。");
            sayHiDalegate.Invoke();
        }

        public void Study()
        {
            Console.WriteLine("学习.net高级班公开课");
        }

        public static void StudyAdvanced()
        {
            Console.WriteLine("学习.net高级班vip课");
        }
    }

    public delegate void SayHiDalegate();

    public enum UserType
    {
        Wuhan = 1,
        Shanghai = 2,
        GuangDong = 3,
        BeiJing = 4
    }
}

委托的嵌套使用,ASP.NETopen in new window Core的核心设计--委托的多层嵌套--

{
    Console.WriteLine("委托的多层嵌套开始。。。。");
    CustomDelegateExtension.Show();
    Console.WriteLine("委托的多层嵌套结束。。。。");
    //俄罗斯套娃---番外装饰器---AOP支持;就是把委托这个箱子,一层一层的包包装;要执行的核心业务逻辑是在最内部的这个箱子中,执行顺序是从最外层执行到最内层---从一层一层的执行出来; 
    //就可以在每一次执行的时候,增加一些业务逻辑;--AOP的支持;装饰器;
    //经过特性+委托多层嵌套的封装---程序的执行环节的自动装撇;如果有十个环节;只需要定义10个特性;
    //分别标记--就可以增加一个处理环节---ASP.NET core的管道处理模型;----666666;
    //套娃确实有点绕---下去后,最好能够自己多看看;
}
{
    /// <summary>
    /// 俄罗斯套娃扩展
    /// </summary>
    public class CustomDelegateExtension
    {

        //public delegate void ShowDelegate();

        //这个委托:接受一个委托类型的参数;返回一个委托类型的参数
        public delegate void ShowDelegate();

        /// <summary>
        /// 
        /// </summary>
        public static void Show()
        {
            //InvokerAction invokerAction = new InvokerAction();
            //invokerAction.Method();

            InvokerAction invokerAction = new InvokerAction();
            Type type = invokerAction.GetType();
            MethodInfo methodInfo = type.GetMethod("Method");
             
            ///实例化一个委托:委托内部包含了一个行为: 行为:执行Method方法
            ShowDelegate showMthod = new ShowDelegate(() =>
            {
                methodInfo.Invoke(invokerAction, null);
            });
             
            //可以完成多层委托的嵌套
            {

                //ShowDelegate showMthod1 = new ShowDelegate(() =>
                //{
                //    showMthod.Invoke();
                //});

                //ShowDelegate showMthod2 = new ShowDelegate(() =>
                //{
                //    showMthod1.Invoke();
                //});

                //ShowDelegate showMthod3 = new ShowDelegate(() =>
                //{
                //    showMthod2.Invoke();
                //});

                //ShowDelegate showMthod4= new ShowDelegate(() =>
                //{
                //    showMthod3.Invoke();
                //});
            }

            //把标记的多个特性中的行为包装到委托中去;
            {
                //ShowDelegate showDelegate1 = null;
                //ShowDelegate showDelegate2 = null;

                ////定义一个特性:--在特性中定义每个环节中要执行的动作:
                //if (methodInfo.IsDefined(typeof(BeforeMethodAttribute), true))
                //{
                //    BeforeMethodAttribute attribute = methodInfo.GetCustomAttribute<BeforeMethodAttribute>();
                //    showDelegate1 = new ShowDelegate(() =>
                //      {
                //          attribute.Do(showMthod);
                //      });

                //    //ShowDelegate showMthod2 = new ShowDelegate(() =>
                //    //{
                //    //    showMthod1.Invoke();
                //    //}); 
                //}

                //if (methodInfo.IsDefined(typeof(BeforeWriteLogAttribute), true))
                //{
                //    BeforeWriteLogAttribute attribute = methodInfo.GetCustomAttribute<BeforeWriteLogAttribute>();
                //    showDelegate2 = new ShowDelegate(() =>
                //    { 
                //        attribute.Do(showDelegate1);
                //    }); 
                //    //ShowDelegate showMthod2 = new ShowDelegate(() =>
                //    //{
                //    //    showMthod1.Invoke();
                //    //}); 
                //}

            }

            ShowDelegate showMethod = new ShowDelegate(() =>
            {
                methodInfo.Invoke(invokerAction, new object[] { 123 });
            }); 
            if (methodInfo.IsDefined(typeof(AbstractMethodAttribute), true))
            {
                foreach (AbstractMethodAttribute attribute in methodInfo.GetCustomAttributes().Reverse())
                {
                    showMethod = attribute.Do(showMethod);
                }
            }
             
            showMethod.Invoke();
        }

        //Method:核心业务逻辑:如果想要在之前做点什么事儿;而且希望前面做的事儿能够自由装配;

        public abstract class AbstractMethodAttribute : Attribute
        {
            /// <summary>
            /// 在xxx 执行之前执行的点业务落
            /// </summary>
            public abstract ShowDelegate Do(ShowDelegate action);
        }

        public class BeforeMethodAttribute : AbstractMethodAttribute
        {
            /// <summary>
            /// 在xxx 执行之前执行的点业务落
            /// </summary>
            public override ShowDelegate Do(ShowDelegate action)
            {
                ShowDelegate actionResult = new ShowDelegate(() =>
                {
                    {
                        Console.WriteLine("在xxx 执行之前执行点业务逻辑");  //这里可以随便写。。。。
                    }

                    action.Invoke();

                    {
                        Console.WriteLine("在xxx 执行之后执行点业务逻辑");  //这里可以随便写。。。。
                    }
                });
                //actionResult.Invoke(); 
                return actionResult;
            }
        }

        public class BeforeWriteLogAttribute : AbstractMethodAttribute
        {
            /// <summary>
            /// 在xxx 执行之前执行的点业务落
            /// </summary>
            public override ShowDelegate Do(ShowDelegate action)
            { 
                ShowDelegate actionResult = new ShowDelegate(() =>
                {
                    {
                        Console.WriteLine("前面写一个日志");  //这里可以随便写。。。。
                    }
                    action.Invoke();
                    {
                        Console.WriteLine("后面写一个日志");  //这里可以随便写。。。。
                    }
                });
                //actionResult.Invoke(); 
                return actionResult;
            }
        }

        public class BeforeWriteLogTEstAttribute : AbstractMethodAttribute
        { 
            public override ShowDelegate Do(ShowDelegate action)
            {
                ShowDelegate actionResult = new ShowDelegate(() =>
                {
                    {
                        Console.WriteLine("之前 BeforeWriteLogTEstAttribute");  //这里可以随便写。。。。
                    }
                    action.Invoke();
                    {
                        Console.WriteLine("之后 BeforeWriteLogTEstAttribute");  //这里可以随便写。。。。
                    }
                });
                //actionResult.Invoke(); 
                return actionResult;
            }
        }

        public class BeforeWriteLogTEst1Attribute : AbstractMethodAttribute
        {
            public override ShowDelegate Do(ShowDelegate action)
            {
                ShowDelegate actionResult = new ShowDelegate(() =>
                {
                    {
                        Console.WriteLine("之前 BeforeWriteLogTEstAttribute");  //这里可以随便写。。。。
                    }
                    action.Invoke();
                    {
                        Console.WriteLine("之后 BeforeWriteLogTEstAttribute");  //这里可以随便写。。。。
                    }
                });
                //actionResult.Invoke(); 
                return actionResult;
            }
        }
    }

    /// <summary>
    /// 普通类---Method方法;
    /// </summary>
    public class InvokerAction
    {
        [BeforeWriteLogTEstAttribute] 
        [BeforeWriteLogAttribute]
        [BeforeMethodAttribute]
        public void Method(int i)
        {
            Console.WriteLine("这里是要执行的核心业务逻辑");
        }
    }
}

框架内置委托Action/Func

//.NET Framework3.0时代--Action/Func
{
    new FrameworkeDelegate().Show();
}
{
    public class FrameworkeDelegate
    {
        public delegate void ShowDelegate();

        public delegate void ShowDelegateInt(int i);

        public delegate int ShowDelegateReturnInt(int i);
         
        public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, in T17>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17);
         
        public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, in T17, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17);

        /// <summary>
        /// 系统内置委托:Action/Func
        /// </summary>
        public void Show()
        {
            //1.Action是来自于System.RunTime的一个声明好的可以带有一个或者多个参数的委托delegate,没有返回值的委托; 
            //2.最多支持16个入参
            //3.想要支持更多的参数呢、---就可以自己些--也只是定义一个委托而已,只是多了一个参数
             
            {
                Console.WriteLine(" ******Action/Func*************");
                ShowDelegate showDelegate = new ShowDelegate(NoreturnNopara);
                showDelegate.Invoke(); 
                ShowDelegateInt showDelegateInt = new ShowDelegateInt(DoNothingInt);
                showDelegate.Invoke(); 
                ShowDelegateReturnInt showDelegateReturnInt = new ShowDelegateReturnInt(ToInt); 
                Action action = new Action(NoreturnNopara);
                action.Invoke(); 
                Action<int> action1 = new Action<int>(DoNothingInt);
                action.Invoke(); 
                Action<int, List<string>, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object> action2 = null;
            } 
            //1.Action是来自于System.RunTime的一个声明好的可以有返回值的委托delegate,也可以有参数 
            //2.如果既然有参数也有返回值---尖扩招中,前面类型参数:输入参数,最后面的类型参数是作为返回值
            //3.最多支持16个入参
            //4.想要支持更多的参数呢、---就可以自己些--也只是定义一个委托而已,只是多了一个参数
            {
                Func<int> func = new Func<int>(ReturnNopara);
                Func<int, int> func1 = new Func<int, int>(ToInt);
                Func<int, string, int> func2 = new Func<int, string, int>(DoNothingIntAndStringNew);
                Func<int, List<string>, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, int> func3 = null;

            }
            //1.我们自己是可以定义委托的,为什么系统框架要给我们提供这样的两个委托呢?

            //2.委托的本质是类:定义多个委托,其实就是新增了多个类;
            {
                //ParameterizedThreadStart:接收一个object类型参数,没有返回值的委托 
                ParameterizedThreadStart parameterizedThread = new ParameterizedThreadStart(ShowObject);
                Thread thread = new Thread(parameterizedThread);

                //3.在使用委托的时候,定义好的两个委托;参数和返回值都是一致的;但是我们在使用的时候,却不能同时使用;委托的本质是类:定义多个委托,其实就是新增了多个类;
                //不行
                //Action<object> action = new Action<object>(ShowObject);
                //Thread thread1 = new Thread(action);
                //不行?
                //ShowObjectDelegate showObjectDelegate = new ShowObjectDelegate(ShowObject);
                //Thread thread1 = new Thread(showObjectDelegate);

                //4.既然是系统框架给我们定义好了这两个委托,自然是希望我们在以后的开发中;都去只是用这两个委托;这样就可以把委托做到统一;我们以后在使用委托的时候,就不用自己再去定义这个委托了;--做到委托类型的统一; 
                //5.那之前定义好的委托呢?  我们是去不掉的,这被称之为历史包袱;
                 
                //Thread thread1 = new Thread();
            }
        }

        public delegate void ShowObjectDelegate(object o);

        public void ShowObject(object o)
        {
            Console.WriteLine("测试一下。。。。");
        }

        private void DoNothingInt(int i)
        {
            Console.WriteLine("This is DoNothing");
        }
        private void DoNothingIntAndString(int i, string j)
        {
            Console.WriteLine("This is DoNothing");
        }

        private int DoNothingIntAndStringNew(int i, string j)
        {
            Console.WriteLine("This is DoNothing");
            return 0;
        }

        private int ToInt(int i)
        {
            return 0;
        }

        private int ReturnNopara()
        {
            return 0;
        }

        private void NoreturnNopara()
        {

        }
    }
}

多播委托/观察者模式

{
    /// <summary>
    /// 多播委托
    /// </summary>
    public class CustomMulticastDelegation
    {
        //public delegate void NoReturnNoPara();

        public void Show()
        {
            Action action = new Action(DoNothing);
            action += DoNothingStatic;
            action += new Student().Study;
            action += Student.StudyAdvanced;
            action += DoNothing;
            action += () =>
            {
                Console.WriteLine("this is 拉姆达表达式。。。");
            };
            {
                //action.BeginInvoke();//开启一个新的线程 去执行委托---注册有多个方法的委托,不能使用BeginInvoke 
                //action.Invoke(); 
                //foreach (Action action1 in action.GetInvocationList())
                //{
                //    action1.Invoke();
                //    //action1.BeginInvoke(null,null);//
                //}
            }
            action -= DoNothing;
            action -= new Student().Study; //没有移除掉:因为不是同一个实例
            action -= () => //没有移除:  其实是因为不同同一个方法---lambda表达式--在底层会生成不同的方法
             {
                 Console.WriteLine("this is 拉姆达表达式。。。");
             };
            action.Invoke();
        }

        private void DoNothing()
        {
            Console.WriteLine("This is DoNothing");
        }

        private void DoNothing(int i)
        {
            Console.WriteLine("This is DoNothing");
        }

        private void DoNothingInt(int i)
        {
            Console.WriteLine("This is DoNothing");
        }
        private void DoNothingIntAndString(int i, string j)
        {
            Console.WriteLine("This is DoNothing");
        }

        private static void DoNothingStatic()
        {
            Console.WriteLine("This is DoNothingStatic");
        }
    }
}