委托
大约 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.NET 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");
}
}
}