CLR Via C# 버전 3 노트(24) - 위임

30064 단어 C#
의뢰는..net에서 리셋 메커니즘을 실현하는 중요한 기술은 특히 서버 프로그램을 작성할 때 의뢰를 빈번하게 사용한다.
주요 내용:
  • 위탁본질
  • 의뢰 체인
  • 동적 의뢰
  •  
    1. 위탁 본질
    위탁의 본질은 하나의 종류이다. 기본적으로 종류를 정의할 수 있는 곳에서 위탁을 정의할 수 있다. C#에서 위탁한 문법은 사실 C#의 문법사탕일 뿐이다.
    다음과 같은 의뢰를 정의합니다.
    using System;
    
    namespace delegate_test
    {
        internal delegate int Sum(int a, int b);
    }

    ILSpy를 사용하면 다음과 같은 IL 코드를 확인할 수 있습니다.
    .class private auto ansi sealed delegate_test.Sum
        extends [mscorlib]System.MulticastDelegate
    {
        // Methods
        .method public hidebysig specialname rtspecialname 
            instance void .ctor (
                object 'object',
                native int 'method'
            ) runtime managed 
        {
        } // end of method Sum::.ctor
    
        .method public hidebysig newslot virtual 
            instance int32 Invoke (
                int32 a,
                int32 b
            ) runtime managed 
        {
        } // end of method Sum::Invoke
    
        .method public hidebysig newslot virtual 
            instance class [mscorlib]System.IAsyncResult BeginInvoke (
                int32 a,
                int32 b,
                class [mscorlib]System.AsyncCallback callback,
                object 'object'
            ) runtime managed 
        {
        } // end of method Sum::BeginInvoke
    
        .method public hidebysig newslot virtual 
            instance int32 EndInvoke (
                class [mscorlib]System.IAsyncResult result
            ) runtime managed 
        {
        } // end of method Sum::EndInvoke
    
    } // end of class delegate_test.Sum

    그중에서 우리는 알 수 있다
  • 의뢰는 하나의 종류로 System에 계승된다.MulticastDelegate.
  • 의뢰류에는 3가지 방법과 하나의 구조 함수
  • 가 있다
  • 위탁구조 함수에 2개의 매개 변수를 입력해야 한다
  •  
    의뢰의 종류를 더욱 잘 이해하기 위해 다음은 간단한 예를 써서 의뢰의 구조 함수를 알아보자.
    using System;
    
    namespace delegate_test
    {
        internal delegate int Sum(int a, int b);
        
        class Program
        {
            public static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
                
                //      ,      IL          
                // IL    Sum          2   (  object   ,   native int  )
                /*
                .method public hidebysig specialname rtspecialname 
                    instance void .ctor (
                            object 'object',
                            native int 'method'
                        ) runtime managed 
                    {
                    } // end of method Sum::.ctor
                */
                Sum s = new Sum(Add);
                
                Console.Write("Press any key to continue . . . ");
                Console.ReadKey(true);
            }
            
            public static int Add(int a, int b)
            {
                return a+b;
            }
        }
    }

    코드에 대한 설명을 참고하십시오. C#에서 실례화된 의뢰의 작성법이 IL에서 본 의뢰의 구조 함수와 일치하지 않음을 알 수 있습니다.
    사실 이것은 C#의 문법 사탕일 뿐입니다. 코드 작성을 편리하게 하기 위해 위의 코드를 컴파일한 후 ILSpy로 IL 코드를 보십시오.
        IL_0000: nop
        IL_0001: ldstr "Hello World!"
        IL_0006: call void [mscorlib]System.Console::WriteLine(string)
        IL_000b: nop
        IL_000c: ldnull
        IL_000d: ldftn int32 delegate_test.Program::Add(int32, int32)
        IL_0013: newobj instance void delegate_test.Sum::.ctor(object, native int)

    우리는 실제 운행할 때 의뢰한 구조 함수, 하나는null, 그리고 하나는함수Add의 주소를 구성하는 것을 발견했다.
    여기 있는 첫 번째 인자 object가null인 이유는, Add 함수는static이기 때문에, 하나의 object를 실례화하지 않아도 된다.
    다음은 static이 아닌 함수 Add2를 만들어서 Object의 값이null인지 확인합니다.
    using System;
    
    namespace delegate_test
    {
        internal delegate int Sum(int a, int b);
        
        class Program
        {
            public static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
                
                //      ,      IL          
                // IL    Sum          2   (  object   ,   native int  )
                /*
                .method public hidebysig specialname rtspecialname 
                    instance void .ctor (
                            object 'object',
                            native int 'method'
                        ) runtime managed 
                    {
                    } // end of method Sum::.ctor
                */
                Sum s = new Sum(Add);
                //  static   Add2
                Sum s2 = new Sum((new Program()).Add2);
                
                Console.Write("Press any key to continue . . . ");
                Console.ReadKey(true);
            }
            
            public static int Add(int a, int b)
            {
                return a+b;
            }
            
            public int Add2(int a, int b)
            {
                return a+b;
            }
        }
    }

    Sum s2 = new Sum((new Program()).Add2); IL은 다음과 같습니다.
        IL_0019: newobj instance void delegate_test.Program::.ctor()
        IL_001e: ldftn instance int32 delegate_test.Program::Add2(int32, int32)
        IL_0024: newobj instance void delegate_test.Sum::.ctor(object, native int)

     
    위탁의 Invoke 함수는 우리가 실제 위탁을 실행할 때 호출하는 함수이며, Begin Invoke와 End Invoke는 비동기적인 상황에 사용된다.
    using System;
    
    namespace delegate_test
    {
        internal delegate int Sum(int a, int b);
        
        class Program
        {
            public static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
                
                //      ,      IL          
                // IL    Sum          2   (  object   ,   native int  )
                /*
                .method public hidebysig specialname rtspecialname 
                    instance void .ctor (
                            object 'object',
                            native int 'method'
                        ) runtime managed 
                    {
                    } // end of method Sum::.ctor
                */
                Sum s = new Sum(Add);
                
                Sum s2 = new Sum((new Program()).Add2);
                
                //         s(5,7)            Invoke  
                Console.WriteLine("5+7="+ s(5,7));
                //
                Console.WriteLine("5+7="+ s.Invoke(5,7));
                
                Console.Write("Press any key to continue . . . ");
                Console.ReadKey(true);
            }
            
            public static int Add(int a, int b)
            {
                return a+b;
            }
            
            public int Add2(int a, int b)
            {
                return a+b;
            }
        }
    }

    s(5,7)는 s.Invoke(5,7)의 간소화 문법이다.
     
    2. 의뢰 체인
    의뢰는 리셋 함수에 사용되는 이상 한 번에 여러 함수를 리셋하여 하나의 의뢰 체인을 형성할 수 있어야 한다.
    이 의뢰 체인에는 리셋 함수를 동적으로 추가하고 줄일 수 있을 것이다.
    실험 코드는 다음과 같습니다.
    using System;
    
    namespace delegate_test
    {
        internal delegate void Print_Sum(int a, int b);
        
        class Program
        {
            public static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
             
                Print_Sum s = null;            
                Print_Sum s1 = new Print_Sum(Add1);            
                Print_Sum s2 = new Print_Sum((new Program()).Add2);
                Print_Sum s3 = new Print_Sum((new Program()).Add3);
                
                s += s1;
                s += s2;
                s += s3;
                
                s(1,2);            
                //       Add2
                s -= s2;
                s(1,2);
                
                Console.Write("Press any key to continue . . . ");
                Console.ReadKey(true);
            }
            
            public static void Add1(int a, int b)
            {
                Console.WriteLine("function Add1.... result is " + (a+b).ToString());
            }
            
            public void Add2(int a, int b)
            {
                Console.WriteLine("function Add2.... result is " + (2*(a+b)).ToString());
            }
            
            public void Add3(int a, int b)
            {
                Console.WriteLine("function Add3.... result is " + (3*(a+b)).ToString());
            }
        }
    }

    운행의 결과도 예상과 일치하지만 사실 그 중의 s+=s1;s-=s2;또한 C#의 문법 사탕으로 실제 사용되는 것은 시스템이다.Delegate의 Combine 메서드 및 Remove 메서드
    관심 있으면 컴파일된 IL 코드를 보십시오.
     
    3. 동적 의뢰
    동적 의뢰는 사실 많이 사용되지 않고 반사와 결합하여 사용된다.호출된 의뢰가 정의한 매개 변수의 개수와 매개 변수의 유형을 확정할 수 없을 때만 동적 의뢰가 필요합니다.
    동적 의뢰를 사용하는 것은 주로 의뢰 실례를 생성하는 Create Delegate 방법과 의뢰를 호출하는 Dynamic Invoke 방법을 사용한다.
    using System;
    using System.Reflection;
    
    internal delegate void print_sum(int a, int b);
    internal delegate void print_string(string a);
    
    public class Dynamic_Delegate
    {
        public static void Main(string[] args)
        {
            //       delegate  ,    ,         args   。
            // Main              
            //     print_sum :
            // delegate_test.exe print_sum Sum 2 3
            //     print_string :
            // delegate_test.exe print_string Str "hello delegate!"
            
            //       
            string delegate_name = args[0];
            string method_name = args[1];
            //   2        ,         ,     
            object[] method_args = new object[args.Length - 2];
            for (int i = 0; i<args.Length-2; i++)
            {
                // print_sum        int 
                if (delegate_name.Equals("print_sum"))
                    method_args[i] = int.Parse(args[2+i]);
                else
                    method_args[i] = args[2+i];
            }
            
            //       
            Type delegate_type = Type.GetType(delegate_name);
            //       
            MethodInfo mi = typeof(Dynamic_Delegate).GetMethod(method_name, BindingFlags.NonPublic | BindingFlags.Static);
            
            //                   delegate            
            Delegate d = Delegate.CreateDelegate(delegate_type, mi);
            
            //       
            d.DynamicInvoke(method_args);
            
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
        
        private static void Sum(int a, int b)
        {
            Console.WriteLine("delegate print_sum....... result is : " + (a+b).ToString());
        }
        
        private static void Str(string a)
        {
            Console.WriteLine("delegate print_string.... result is : " + a);
        }
    }

    컴파일된 프로그램 집합 (내 프로그램 집합 이름은 delegate test.exe) 에 따라 명령줄에 각각 다음 명령을 입력하여 다른 delegate를 호출합니다.
    delegate_test.exe print_sum Sum 2 3
    delegate_test.exe print_string Str "hello delegate!"

    좋은 웹페이지 즐겨찾기