1,委托列子
internal delegate void Feedback(int value); class DelegateRef { public static void StaticDelegateDeomo() { Console.WriteLine("---------------static delegate Demo ------------"); Counter(1, 3, null); Counter(1, 3, FeedBackToConsole); Counter(1, 3, FeedBackToMsgBox); Console.WriteLine(); } public static void InstanceDelegateDemo() { Console.WriteLine("----------------Instance Delegate Demo ---------"); DelegateRef p = new DelegateRef(); Counter(1, 3, p.FeedBackToFile); Console.WriteLine(); } public static void ChainDelegateDemo1(DelegateRef p) { Console.WriteLine("----------------Chain Delegate Demo ----------"); Feedback chain = FeedBackToConsole; chain += FeedBackToMsgBox; chain += p.FeedBackToFile; Counter(1, 2, chain); Console.WriteLine(); chain -= FeedBackToMsgBox; Counter(1, 2, chain); } private static void Counter(int from, int to, Feedback fb) { for (int val = from; val <= to; val++) { if (fb != null) fb(val); } } private static void FeedBackToConsole(int value) { Console.WriteLine("Item=" + value); } private static void FeedBackToMsgBox(int value) { MessageBox.Show("Item=" + value); } private void FeedBackToFile(int value) { using(StreamWriter sw=new StreamWriter("Status", true)) { sw.WriteLine("Item=" + value); } } public static void CallDelegateDemo() { StaticDelegateDeomo(); InstanceDelegateDemo(); ChainDelegateDemo1(new DelegateRef()); } }
2,委托揭秘
在 Conter之中,实际上 +=是创建了Delegate的实列,并且调用了Combine函数,触发调用了invoke函数,移除调用了,remove函数
.method public hidebysig static void ChainDelegateDemo1(class ClrFromCSharp_2_2.LearnDelegate.DelegateRef p) cil managed // SIG: 00 01 01 12 60 { // 方法在 RVA 0x2ad4 处开始 // 代码大小 122 (0x7a) .maxstack 3 .locals init ([0] class ClrFromCSharp_2_2.LearnDelegate.Feedback chain) IL_0000: /* 00 | */ nop IL_0001: /* 72 | (70)000207 */ ldstr "----------------Chain Delegate Demo ----------" IL_0006: /* 28 | (0A)00001C */ call void [mscorlib]System.Console::WriteLine(string) IL_000b: /* 00 | */ nop IL_000c: /* 14 | */ ldnull IL_000d: /* FE06 | (06)000059 */ ldftn void ClrFromCSharp_2_2.LearnDelegate.DelegateRef::FeedBackToConsole(int32) IL_0013: /* 73 | (06)000051 */ newobj instance void ClrFromCSharp_2_2.LearnDelegate.Feedback::.ctor(object, native int) IL_0018: /* 0A | */ stloc.0 IL_0019: /* 06 | */ ldloc.0 IL_001a: /* 14 | */ ldnull IL_001b: /* FE06 | (06)00005A */ ldftn void ClrFromCSharp_2_2.LearnDelegate.DelegateRef::FeedBackToMsgBox(int32) IL_0021: /* 73 | (06)000051 */ newobj instance void ClrFromCSharp_2_2.LearnDelegate.Feedback::.ctor(object, native int) IL_0026: /* 28 | (0A)00003C */ call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate) IL_002b: /* 74 | (02)000017 */ castclass ClrFromCSharp_2_2.LearnDelegate.Feedback IL_0030: /* 0A | */ stloc.0 IL_0031: /* 06 | */ ldloc.0 IL_0032: /* 02 | */ ldarg.0 IL_0033: /* FE06 | (06)00005B */ ldftn instance void ClrFromCSharp_2_2.LearnDelegate.DelegateRef::FeedBackToFile(int32) IL_0039: /* 73 | (06)000051 */ newobj instance void ClrFromCSharp_2_2.LearnDelegate.Feedback::.ctor(object, native int) IL_003e: /* 28 | (0A)00003C */ call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate) IL_0043: /* 74 | (02)000017 */ castclass ClrFromCSharp_2_2.LearnDelegate.Feedback IL_0048: /* 0A | */ stloc.0 IL_0049: /* 17 | */ ldc.i4.1 IL_004a: /* 18 | */ ldc.i4.2 IL_004b: /* 06 | */ ldloc.0 IL_004c: /* 28 | (06)000058 */ call void ClrFromCSharp_2_2.LearnDelegate.DelegateRef::Counter(int32, int32, class ClrFromCSharp_2_2.LearnDelegate.Feedback) IL_0051: /* 00 | */ nop IL_0052: /* 28 | (0A)000049 */ call void [mscorlib]System.Console::WriteLine() IL_0057: /* 00 | */ nop IL_0058: /* 06 | */ ldloc.0 IL_0059: /* 14 | */ ldnull IL_005a: /* FE06 | (06)00005A */ ldftn void ClrFromCSharp_2_2.LearnDelegate.DelegateRef::FeedBackToMsgBox(int32) IL_0060: /* 73 | (06)000051 */ newobj instance void ClrFromCSharp_2_2.LearnDelegate.Feedback::.ctor(object, native int) IL_0065: /* 28 | (0A)00003F */ call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate) IL_006a: /* 74 | (02)000017 */ castclass ClrFromCSharp_2_2.LearnDelegate.Feedback IL_006f: /* 0A | */ stloc.0 IL_0070: /* 17 | */ ldc.i4.1 IL_0071: /* 18 | */ ldc.i4.2 IL_0072: /* 06 | */ ldloc.0 IL_0073: /* 28 | (06)000058 */ call void ClrFromCSharp_2_2.LearnDelegate.DelegateRef::Counter(int32, int32, class ClrFromCSharp_2_2.LearnDelegate.Feedback) IL_0078: /* 00 | */ nop IL_0079: /* 2A | */ ret } // end of method DelegateRef::ChainDelegateDemo1 }
3,利用GetInvocationList()的方式,显示调用每一个委托,这样可以显式的处理每个委托的返回值和异常,否则
- 当出现异常的时候,链表里面的下面的委托不会执行
- 当出现阻塞时候,链表里面的下面的委托不会执行
4,委托和反射
internal static class DelegateReflection { // Here are some different delegate definitions private delegate Object TwoInt32s(Int32 n1, Int32 n2); private delegate Object OneString(String s1); public static void Go(String[] args) { if (args.Length < 2) { String fileName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);//获取执行文件的名称,但是没用 String usage =//提示用法 @"Usage:" + "{0}{1} delType methodName [Arg1] [Arg2]" + "{0} where delType must be TwoInt32s or OneString" + "{0} if delType is TwoInt32s, methodName must be Add or Subtract" + "{0} if delType is OneString, methodName must be NumChars or Reverse" + "{0}" + "{0}Examples:" + "{0} {1}TwoInt32s Add 123 321" + "{0} {1}TwoInt32s Subtract 123 321" + "{0} {1}OneString NumChars "Hello there"" + "{0} {1}OneString Reverse "Hello there""; Console.WriteLine(usage, Environment.NewLine, "DelegateReflection+"); return; } // Convert the delType argument to a delegate type Type delType = Type.GetType(args[0]);//1,利用string返回类型Type...注意:DelegateReflection+TwoInt32s才是其TYPE if (delType == null) { Console.WriteLine("Invalid delType argument: " + args[0]); return; } Delegate d; try { // Convert the Arg1 argument to a method//注意,在某个类里面获取某个方法..方法名是arg[1],Add MethodInfo mi = typeof(DelegateReflection).GetMethod(args[1], BindingFlags.NonPublic | BindingFlags.Static);//2,获取类中方法 // Create a delegate object that wraps the static method d = Delegate.CreateDelegate(delType, mi);//3,利用该方法将类的静态方法--->传送至委托. } catch (ArgumentException) { Console.WriteLine("Invalid methodName argument: " + args[1]); return; } // Create an array that that will contain just the arguments // to pass to the method via the delegate object Object[] callbackArgs = new Object[args.Length - 2]; if (d.GetType() == typeof(TwoInt32s)) {//类型比较 try { // Convert the String arguments to Int32 arguments for (Int32 a = 2; a < args.Length; a++) callbackArgs[a - 2] = Int32.Parse(args[a]); } catch (FormatException) { Console.WriteLine("Parameters must be integers."); return; } } if (d.GetType() == typeof(OneString)) { // Just copy the String argument Array.Copy(args, 2, callbackArgs, 0, callbackArgs.Length); } try { // Invoke the delegate and show the result Object result = d.DynamicInvoke(callbackArgs);//4,调用委托,动态给与参数.参数是object[]---必须匹配. Console.WriteLine("Result = " + result); } catch (TargetParameterCountException) { Console.WriteLine("Incorrect number of parameters specified."); } } // This callback method takes 2 Int32 arguments private static Object Add(Int32 n1, Int32 n2) { return n1 + n2; } // This callback method takes 2 Int32 arguments private static Object Subtract(Int32 n1, Int32 n2) { return n1 - n2; } // This callback method takes 1 String argument private static Object NumChars(String s1) { return s1.Length; } // This callback method takes 1 String argument private static Object Reverse(String s1) { Char[] chars = s1.ToCharArray(); Array.Reverse(chars); return new String(chars); } }
- 新建委托TYPE
- 从类中查找静态方法
- 利用Delegate.CreateDelegate建立类中静态方法的委托.
- 利用d.DynamicInvoke(object[])来调用委托,其中参数是一个数组匹配原静态方法的参数.如果不一致会报参数不匹配错误.
- TargetParameterCountException