Прочитать на английском

Поделиться через


DynamicMethod.CreateDelegate Метод

Определение

Завершает динамический метод и создает делегат, который может использоваться для его выполнения.

Перегрузки

CreateDelegate(Type)

Завершает динамический метод и создает делегат, который может использоваться для его выполнения.

CreateDelegate(Type, Object)

Завершает динамический метод и создает делегат, который может использоваться для его выполнения, указывая тип делегата и объект, к которому привязан делегат.

CreateDelegate(Type)

Исходный код:
DynamicMethod.cs
Исходный код:
DynamicMethod.CoreCLR.cs
Исходный код:
DynamicMethod.CoreCLR.cs

Завершает динамический метод и создает делегат, который может использоваться для его выполнения.

public override sealed Delegate CreateDelegate (Type delegateType);
[System.Runtime.InteropServices.ComVisible(true)]
public Delegate CreateDelegate (Type delegateType);
[System.Runtime.InteropServices.ComVisible(true)]
public override sealed Delegate CreateDelegate (Type delegateType);

Параметры

delegateType
Type

Тип делегата, подпись которого совпадает с подписью динамического метода.

Возвращаемое значение

Делегат указанного типа, который может использоваться для выполнения динамического метода.

Атрибуты

Исключения

У динамического метода отсутствует тело метода.

delegateType имеет неверное число параметров или неправильные типы параметров.

Примеры

В следующем примере кода создается динамический метод, который принимает два параметра. В примере создается простая функция, которая выводит первый параметр в консоль, а в примере используется второй параметр в качестве возвращаемого значения метода. В примере завершается метод путем создания делегата, вызывается делегат с другими параметрами и, наконец, вызывается динамический метод с помощью Invoke метода .

using System;
using System.Reflection;
using System.Reflection.Emit;
using Microsoft.VisualBasic;

public class Test
{
    // Declare a delegate that will be used to execute the completed
    // dynamic method.
    private delegate int HelloInvoker(string msg, int ret);

    public static void Main()
    {
        // Create an array that specifies the types of the parameters
        // of the dynamic method. This method has a string parameter
        // and an int parameter.
        Type[] helloArgs = {typeof(string), typeof(int)};

        // Create a dynamic method with the name "Hello", a return type
        // of int, and two parameters whose types are specified by the
        // array helloArgs. Create the method in the module that
        // defines the Test class.
        DynamicMethod hello = new DynamicMethod("Hello",
            typeof(int),
            helloArgs,
            typeof(Test).Module);

        // Create an array that specifies the parameter types of the
        // overload of Console.WriteLine to be used in Hello.
        Type[] writeStringArgs = {typeof(string)};
        // Get the overload of Console.WriteLine that has one
        // String parameter.
        MethodInfo writeString =
            typeof(Console).GetMethod("WriteLine", writeStringArgs);

        // Get an ILGenerator and emit a body for the dynamic method.
        ILGenerator il = hello.GetILGenerator();
        // Load the first argument, which is a string, onto the stack.
        il.Emit(OpCodes.Ldarg_0);
        // Call the overload of Console.WriteLine that prints a string.
        il.EmitCall(OpCodes.Call, writeString, null);
        // The Hello method returns the value of the second argument;
        // to do this, load the onto the stack and return.
        il.Emit(OpCodes.Ldarg_1);
        il.Emit(OpCodes.Ret);

        // Create a delegate that represents the dynamic method. This
        // action completes the method, and any further attempts to
        // change the method will cause an exception.
        HelloInvoker hi =
            (HelloInvoker) hello.CreateDelegate(typeof(HelloInvoker));

        // Use the delegate to execute the dynamic method. Save and
        // print the return value.
        int retval = hi("\r\nHello, World!", 42);
        Console.WriteLine("Executing delegate hi(\"Hello, World!\", 42) returned {0}",
            retval);

        // Do it again, with different arguments.
        retval = hi("\r\nHi, Mom!", 5280);
        Console.WriteLine("Executing delegate hi(\"Hi, Mom!\", 5280) returned {0}",
            retval);

        // Create an array of arguments to use with the Invoke method.
        object[] invokeArgs = {"\r\nHello, World!", 42};
        // Invoke the dynamic method using the arguments. This is much
        // slower than using the delegate, because you must create an
        // array to contain the arguments, and ValueType arguments
        // must be boxed.
        object objRet = hello.Invoke(null, invokeArgs);
        Console.WriteLine("hello.Invoke returned {0}", objRet);
    }
}

Комментарии

CreateDelegate Вызов метода или Invoke метода завершает динамический метод. Любая дальнейшая попытка изменения динамического метода, например изменение определений параметров или создание более промежуточного языка Майкрософт (MSIL), игнорируется; исключение не создается.

Чтобы создать тело метода для динамического метода при наличии собственного генератора GetDynamicILInfo MSIL, вызовите метод для получения DynamicILInfo объекта . Если у вас нет собственного генератора GetILGenerator MSIL, вызовите метод , чтобы получить ILGenerator объект, который можно использовать для создания тела метода.

См. также раздел

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

CreateDelegate(Type, Object)

Исходный код:
DynamicMethod.cs
Исходный код:
DynamicMethod.CoreCLR.cs
Исходный код:
DynamicMethod.CoreCLR.cs

Завершает динамический метод и создает делегат, который может использоваться для его выполнения, указывая тип делегата и объект, к которому привязан делегат.

public override sealed Delegate CreateDelegate (Type delegateType, object? target);
public override sealed Delegate CreateDelegate (Type delegateType, object target);
[System.Runtime.InteropServices.ComVisible(true)]
public Delegate CreateDelegate (Type delegateType, object target);
[System.Runtime.InteropServices.ComVisible(true)]
public override sealed Delegate CreateDelegate (Type delegateType, object target);

Параметры

delegateType
Type

Тип делегата, подпись которого совпадает с подписью динамического метода минус первый параметр.

target
Object

Объект, к которому привязан делегат. Должен быть того же типа, что и первый параметр динамического метода.

Возвращаемое значение

Делегат указанного типа, который может использоваться для выполнения динамического метода с указанным целевым объектом.

Атрибуты

Исключения

У динамического метода отсутствует тело метода.

target не относится к тому же типу, что и первый параметр динамического метода, и не может быть назначен этому типу.

-или-

delegateType имеет неверное число параметров или неправильные типы параметров.

Примеры

В следующем примере кода создается делегат, который привязывает DynamicMethod к экземпляру типа , чтобы метод действовал на один и тот же экземпляр при каждом вызове.

В примере кода определяется класс Example с закрытым полем, класс с именем DerivedFromExample , производный от первого класса, тип делегата с именем UseLikeStatic , который возвращает Int32 и имеет параметры типа Example и Int32, а также тип делегата с именем UseLikeInstance , который возвращает Int32 и имеет один параметр типа Int32.

Затем в примере кода создается объект , DynamicMethod который изменяет частное поле экземпляра Example и возвращает предыдущее значение.

Примечание

Как правило, изменение внутренних полей классов не является хорошей практикой объектно-ориентированного программирования.

В примере кода создается экземпляр , Example а затем два делегата. Первый относится к типу UseLikeStatic, который имеет те же параметры, что и динамический метод. Второй тип имеет тип UseLikeInstance, в котором отсутствует первый параметр (типа Example). Этот делегат создается с помощью перегрузки CreateDelegate(Type, Object) метода; вторым параметром перегрузки этого метода является экземпляр Example, в данном случае только что созданный экземпляр, привязанный к только что созданному делегату. При каждом вызове этого делегата динамический метод действует на привязанный Exampleэкземпляр .

Примечание

Это пример незащищенных правил для привязки делегатов, представленных в платформа .NET Framework 2.0, а также новые перегрузки Delegate.CreateDelegate метода . Дополнительные сведения см. в описании класса Delegate.

Вызывается UseLikeStatic делегат, передавая экземпляр Example , привязанный к делегату UseLikeInstance . UseLikeInstance Затем вызывается делегат, чтобы оба делегата действовали на одном экземпляре Example. Изменения значений внутреннего поля отображаются после каждого вызова. Наконец, UseLikeInstance делегат привязывается к экземпляру DerivedFromExample, и вызовы делегата повторяются.

using System;
using System.Reflection;
using System.Reflection.Emit;

// These classes are for demonstration purposes.
//
public class Example
{
    private int id = 0;
    public Example(int id)
    {
        this.id = id;
    }
    public int ID { get { return id; }}
}

public class DerivedFromExample : Example
{
    public DerivedFromExample(int id) : base(id) {}
}

// Two delegates are declared: UseLikeInstance treats the dynamic
// method as if it were an instance method, and UseLikeStatic
// treats the dynamic method in the ordinary fashion.
//
public delegate int UseLikeInstance(int newID);
public delegate int UseLikeStatic(Example ex, int newID);

public class Demo
{
    public static void Main()
    {
        // This dynamic method changes the private id field. It has
        // no name; it returns the old id value (return type int);
        // it takes two parameters, an instance of Example and
        // an int that is the new value of id; and it is declared
        // with Example as the owner type, so it can access all
        // members, public and private.
        //
        DynamicMethod changeID = new DynamicMethod(
            "",
            typeof(int),
            new Type[] { typeof(Example), typeof(int) },
            typeof(Example)
        );

        // Get a FieldInfo for the private field 'id'.
        FieldInfo fid = typeof(Example).GetField(
            "id",
            BindingFlags.NonPublic | BindingFlags.Instance
        );

        ILGenerator ilg = changeID.GetILGenerator();

        // Push the current value of the id field onto the
        // evaluation stack. It's an instance field, so load the
        // instance of Example before accessing the field.
        ilg.Emit(OpCodes.Ldarg_0);
        ilg.Emit(OpCodes.Ldfld, fid);

        // Load the instance of Example again, load the new value
        // of id, and store the new field value.
        ilg.Emit(OpCodes.Ldarg_0);
        ilg.Emit(OpCodes.Ldarg_1);
        ilg.Emit(OpCodes.Stfld, fid);

        // The original value of the id field is now the only
        // thing on the stack, so return from the call.
        ilg.Emit(OpCodes.Ret);

        // Create a delegate that uses changeID in the ordinary
        // way, as a static method that takes an instance of
        // Example and an int.
        //
        UseLikeStatic uls =
            (UseLikeStatic) changeID.CreateDelegate(
                typeof(UseLikeStatic)
            );

        // Create an instance of Example with an id of 42.
        //
        Example ex = new Example(42);

        // Create a delegate that is bound to the instance of
        // of Example. This is possible because the first
        // parameter of changeID is of type Example. The
        // delegate has all the parameters of changeID except
        // the first.
        UseLikeInstance uli =
            (UseLikeInstance) changeID.CreateDelegate(
                typeof(UseLikeInstance),
                ex
            );

        // First, change the value of id by calling changeID as
        // a static method, passing in the instance of Example.
        //
        Console.WriteLine(
            "Change the value of id; previous value: {0}",
            uls(ex, 1492)
        );

        // Change the value of id again using the delegate bound
        // to the instance of Example.
        //
        Console.WriteLine(
            "Change the value of id; previous value: {0}",
            uli(2700)
        );

        Console.WriteLine("Final value of id: {0}", ex.ID);

        // Now repeat the process with a class that derives
        // from Example.
        //
        DerivedFromExample dfex = new DerivedFromExample(71);

        uli = (UseLikeInstance) changeID.CreateDelegate(
                typeof(UseLikeInstance),
                dfex
            );

        Console.WriteLine(
            "Change the value of id; previous value: {0}",
            uls(dfex, 73)
        );
        Console.WriteLine(
            "Change the value of id; previous value: {0}",
            uli(79)
        );
        Console.WriteLine("Final value of id: {0}", dfex.ID);
    }
}

/* This code example produces the following output:

Change the value of id; previous value: 42
Change the value of id; previous value: 1492
Final value of id: 2700
Change the value of id; previous value: 71
Change the value of id; previous value: 73
Final value of id: 79
 */

Комментарии

Эта перегрузка метода создает делегат, привязанный к конкретному объекту. Считается, что такой делегат закрыт из-за своего первого аргумента. Хотя метод является статическим, он действует так же, как если бы он был методом экземпляра; экземпляр имеет значение target.

Эта перегрузка метода должна target иметь тот же тип, что и первый параметр динамического метода, или быть назначена этому типу (например, производному классу). Сигнатура delegateType имеет все параметры динамического метода, кроме первого. Например, если динамический метод имеет параметры , и , то delegateType имеет параметры Int32 и Byte; target имеет тип String.ByteInt32String

CreateDelegate Вызов метода или Invoke метода завершает динамический метод. Любая дальнейшая попытка изменения динамического метода, например изменение определений параметров или создание более промежуточного языка Майкрософт (MSIL), игнорируется; исключение не создается.

Чтобы создать тело метода для динамического метода при наличии собственного генератора GetDynamicILInfo MSIL, вызовите метод для получения DynamicILInfo объекта . Если у вас нет собственного генератора GetILGenerator MSIL, вызовите метод , чтобы получить ILGenerator объект, который можно использовать для создания тела метода.

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1