• clr via c# delegate


    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);
       }
    }
    1. 新建委托TYPE
    2. 从类中查找静态方法
    3. 利用Delegate.CreateDelegate建立类中静态方法的委托.
    4. 利用d.DynamicInvoke(object[])来调用委托,其中参数是一个数组匹配原静态方法的参数.如果不一致会报参数不匹配错误.
    5. TargetParameterCountException

  • 相关阅读:
    三级菜单的实现方式
    简单登录接口实践
    C++中的set和java的hashset有何区别?
    css 利用文档结构给列表添加样式
    谈谈我对JS中this的理解
    谈谈我对JS原型的理解
    使用node.js,实现简单的JS文件合并小工具
    谈谈我对JS闭包的理解
    谈谈我对JS作用域的理解
    模拟实现 百度翻译 右下方的可折叠的分享按钮列表
  • 原文地址:https://www.cnblogs.com/frogkiller/p/12285259.html
Copyright © 2020-2023  润新知