情報
要求されたトピックは次のとおりです。しかし、このトピックはこのライブラリには含まれていません。

DynamicMethod.CreateDelegate メソッド (Type, Object)

2013/12/12

動的メソッドを完了し、デリゲート型とデリゲートのバインド先となるオブジェクトを指定して、メソッドの実行に使用できるデリゲートを作成します。

Namespace:  System.Reflection.Emit
アセンブリ:  mscorlib (mscorlib.dll 内)

public override sealed Delegate CreateDelegate(
	Type delegateType,
	Object target
)

パラメーター

delegateType
型: System.Type
1 つ目のパラメーターがない、シグネチャが動的メソッドのシグネチャと一致するデリゲート型。
target
型: System.Object
デリゲートのバインド先となるオブジェクト。動的メソッドの 1 つ目のパラメーターと同じ型であることが必要です。

戻り値

型: System.Delegate
指定した対象オブジェクトで動的メソッドの実行に使用できる、指定した型のデリゲート。

例外条件
InvalidOperationException

動的メソッドにメソッド本体がありません。

ArgumentException

target が動的メソッドの最初のパラメーターと同じ型でないため、この型に割り当てることはできません。

または

delegateType のパラメーターの数に誤りがあるか、パラメーターの型に誤りがあります。

このメソッド オーバーロードは、特定のオブジェクトにバインドされたデリゲートを作成します。このようなデリゲートは、その最初の引数に対して閉じられていると言います。このメソッドは静的ですが、インスタンス メソッドと同様に機能します。このインスタンスは target です。

このメソッド オーバーロードでは、動的メソッドの最初のパラメーターと同じ型、またはその型に割り当て可能な (派生クラスなどの) target が必要となります。delegateType のシグネチャは、最初のパラメーターを除く、動的メソッドのすべてのパラメーターを持ちます。たとえば、動的メソッドに StringInt32、および Byte の各パラメーターがある場合、delegateTypeInt32 パラメーターと Byte パラメーターを持ちます。targetString 型です。

CreateDelegate メソッドまたは Invoke メソッドを呼び出すと、動的メソッドが完了します。パラメーター定義の変更や、MSIL (Microsoft Intermediate Language) の出力など、動的メソッドをそれ以上変更しようとしても無視されます。この場合、例外はスローされません。

次の例では、動的メソッドを定義し、メソッドの第 1 パラメーターにバインドされたオブジェクトでデリゲートを作成します。

この例では、Number という名前のフィールドを持った Base という名前のクラスを定義し、さらに、そのクラスから派生した DerivedFromBase という名前のクラスを定義しています。このコードでは次の 2 つのデリゲート型を定義しています。1 つは UseLikeStatic という名前で、Int32 を返し、Base および Int32 型のパラメーターを持ちます。もう 1 つは UseLikeInstance という名前で、Int32 を返し、Int32 型のパラメーターを持ちます。

次に、Base のインスタンスの Number フィールドを変更し、以前の値を返す DynamicMethod を作成します。

このコード例では、Base のインスタンスを作成した後、2 つのデリゲートを作成しています。最初のデリゲートは、動的メソッドと同じパラメーターを持つ UseLikeStatic 型のデリゲートです。2 番目のデリゲートは、最初のパラメーター (Base 型) のない UseLikeInstance 型のデリゲートです。このデリゲートは、CreateDelegate(Type, Object) メソッド オーバーロードを使用して作成されます。このメソッド オーバーロードの 2 番目のパラメーターは Base のインスタンスです。新しく作成されたデリゲートには、このインスタンスがバインドされます。このデリゲートを呼び出すたびに、動的メソッドは Base のバインドされたインスタンスに対して機能します。

メモメモ:

これは、Delegate.CreateDelegate メソッドでもサポートされている、デリゲート バインディングの緩やかな規則の一例です。詳細については、Delegate クラスを参照してください。

UseLikeStatic デリゲートが呼び出され、UseLikeInstance デリゲートにバインドされた Base の同じインスタンスが渡されます。次に、UseLikeInstance デリゲートが呼び出され、この 2 つのデリゲートが Base の同じインスタンスに対して機能します。Number フィールドの値の変更は、各呼び出しの後に表示されます。最後に、UseLikeInstance デリゲートが DerivedFromBase のインスタンスにバインドされ、デリゲートの呼び出しが繰り返されます。

メモメモ:

この例を実行するには、「Windows Phone での静的 TextBlock コントロールのあるコード例のビルド」を参照してください。


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

// These classes are for demonstration purposes.
//
public class Base
{
   public int Number = 0;
   public Base(int initialNumber)
   {
      this.Number = initialNumber;
   }
}

public class DerivedFromBase : Base
{
   public DerivedFromBase(int initialNumber) : base(initialNumber) { }
}

// 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 newNumber);
public delegate int UseLikeStatic(Base ba, int newNumber);

public class Example
{
   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {
      // This dynamic method sets the public Number field of an instance
      // of Base, and returns the previous value. The method has no name. 
      // It takes two parameters, an instance of Base and an Integer that
      // is the new field value. 
      //
      DynamicMethod changeNumber = new DynamicMethod(
          "",
          typeof(int),
          new Type[] { typeof(Base), typeof(int) }
      );

      // Get a FieldInfo for the public field 'Number'.
      FieldInfo fnum = typeof(Base).GetField(
          "Number",
          BindingFlags.Public | BindingFlags.Instance
      );

      ILGenerator ilg = changeNumber.GetILGenerator();

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

      // Load the instance of Base again, load the new value 
      // of Number, and store the new field value. 
      ilg.Emit(OpCodes.Ldarg_0);
      ilg.Emit(OpCodes.Ldarg_1);
      ilg.Emit(OpCodes.Stfld, fnum);

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


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

      // Create an instance of Base with a Number of 42.
      //
      Base ba = new Base(42);

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

      // First, change the value of Number by calling changeNumber as
      // a static method, passing in the instance of Base.
      //
      outputBlock.Text += String.Format(
          "Change the value of Number; previous value: {0}",
          uls(ba, 1492)
      ) + "\n";

      // Change the value of Number again using the delegate bound
      // to the instance of Base.
      //
      outputBlock.Text += String.Format(
          "Change the value of Number; previous value: {0}",
          uli(2700)
      ) + "\n";

      outputBlock.Text += String.Format("Final value of Number: {0}", ba.Number) + "\n";


      // Now repeat the process with a class that derives
      // from Base.
      //
      DerivedFromBase dfba = new DerivedFromBase(71);

      uli = (UseLikeInstance)changeNumber.CreateDelegate(
              typeof(UseLikeInstance),
              dfba
          );

      outputBlock.Text += String.Format(
          "Change the value of Number; previous value: {0}",
          uls(dfba, 73)
      ) + "\n";
      outputBlock.Text += String.Format(
          "Change the value of Number; previous value: {0}",
          uli(79)
      ) + "\n";
      outputBlock.Text += String.Format("Final value of Number: {0}", dfba.Number) + "\n";
   }
}

/* This example produces the following output:

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


Windows Phone OS

サポート: 8.0, 7.1

表示: