型を動的に読み込み使用する
リフレクションは、言語コンパイラで使用される、暗黙の遅延バインディングを実装するインフラストラクチャを提供します。 バインディングとは、一意に指定した型に対応する宣言 (つまり、実装) を検索するプロセスです。 このプロセスがコンパイル時ではなく、実行時に発生する場合、それは遅延バインディングと呼ばれます。 Visual Basic のコードでは、暗黙の遅延バインディングを使用できます。Visual Basic のコンパイラからは、オブジェクトの型の取得にリフレクションを使用するヘルパー メソッドが呼び出されます。 ヘルパー メソッドに渡される引数により、実行時に適切なメソッドが呼び出されます。 これらの引数は、メソッドを呼び出すインスタンス (オブジェクト)、呼び出されたメソッド名 (文字列)、呼び出されたメソッドに渡される引数 (オブジェクトの配列) です。
次の例では、Visual Basic コンパイラがリフレクションを暗黙的に使用して、コンパイル時には型が不明なオブジェクトのメソッドを呼び出します。 HelloWorld
クラスには、PrintHello
メソッドに渡されるテキストと連結された "Hello World" を出力する PrintHello
メソッドがあります。 この例で呼び出される PrintHello
メソッドは、実際には Type.InvokeMember です。Visual Basic コードを使用すると、実行時 (遅延バインディング) ではなく、コンパイル時 (早期バインディング) にオブジェクト (helloObj
) の型が認識されたかのように、PrintHello
メソッドを呼び出すことができます。
Module Hello
Sub Main()
' Sets up the variable.
Dim helloObj As Object
' Creates the object.
helloObj = new HelloWorld()
' Invokes the print method as if it was early bound
' even though it is really late bound.
helloObj.PrintHello("Visual Basic Late Bound")
End Sub
End Module
カスタム バインド
コンパイラが暗黙的に遅延バインディングに使用するだけではなく、コードでリフレクションを使用して、明示的に遅延バインディングを実現できます。
共通言語ランタイムでは、複数のプログラミング言語をサポートしていますが、バインド規則は言語によって異なります。 事前バインディングの場合、コード ジェネレーターがバインディングを完全に制御できます。 ただし、リフレクションによる遅延バインディングでは、カスタム バインドでバインディングを制御する必要があります。 Binder クラスには、メンバーの選択と呼び出しのカスタム コントロールがあります。
カスタム バインドを使用すると、実行時にアセンブリを読み込み、そのアセンブリ内の型についての情報を取得し、必要な型を指定し、その後でメソッドを呼び出したり、その型のフィールドやプロパティにアクセスしたりできます。 この方法は、コンパイル時にオブジェクトの種類を特定できない場合、たとえば、オブジェクトの型がユーザーによる入力に依存するような場合に便利です。
引数の型変換のない単純なカスタム バインダーの例を次に示します。 メインの例の前には、Simple_Type.dll
のコードを示しています。 Simple_Type.dll
を必ず構成し、プロジェクトのビルド時にこれに対する参照を含めます。
// Code for building SimpleType.dll.
using namespace System;
using namespace System::Reflection;
using namespace System::Globalization;
namespace Simple_Type
{
public ref class MySimpleClass
{
public:
void MyMethod(String^ str, int i)
{
Console::WriteLine("MyMethod parameters: {0}, {1}", str, i);
}
void MyMethod(String^ str, int i, int j)
{
Console::WriteLine("MyMethod parameters: {0}, {1}, {2}",
str, i, j);
}
};
}
using namespace Simple_Type;
namespace Custom_Binder
{
// ****************************************************
// A simple custom binder that provides no
// argument type conversion.
// ****************************************************
public ref class MyCustomBinder : Binder
{
public:
virtual MethodBase^ BindToMethod(
BindingFlags bindingAttr,
array<MethodBase^>^ match,
array<Object^>^% args,
array<ParameterModifier>^ modifiers,
CultureInfo^ culture,
array<String^>^ names,
Object^% state) override
{
if (match == nullptr)
{
throw gcnew ArgumentNullException("match");
}
// Arguments are not being reordered.
state = nullptr;
// Find a parameter match and return the first method with
// parameters that match the request.
for each (MethodBase^ mb in match)
{
array<ParameterInfo^>^ parameters = mb->GetParameters();
if (ParametersMatch(parameters, args))
{
return mb;
}
}
return nullptr;
}
virtual FieldInfo^ BindToField(BindingFlags bindingAttr,
array<FieldInfo^>^ match, Object^ value, CultureInfo^ culture) override
{
if (match == nullptr)
{
throw gcnew ArgumentNullException("match");
}
for each (FieldInfo^ fi in match)
{
if (fi->GetType() == value->GetType())
{
return fi;
}
}
return nullptr;
}
virtual MethodBase^ SelectMethod(
BindingFlags bindingAttr,
array<MethodBase^>^ match,
array<Type^>^ types,
array<ParameterModifier>^ modifiers) override
{
if (match == nullptr)
{
throw gcnew ArgumentNullException("match");
}
// Find a parameter match and return the first method with
// parameters that match the request.
for each (MethodBase^ mb in match)
{
array<ParameterInfo^>^ parameters = mb->GetParameters();
if (ParametersMatch(parameters, types))
{
return mb;
}
}
return nullptr;
}
virtual PropertyInfo^ SelectProperty(
BindingFlags bindingAttr,
array<PropertyInfo^>^ match,
Type^ returnType,
array<Type^>^ indexes,
array<ParameterModifier>^ modifiers) override
{
if (match == nullptr)
{
throw gcnew ArgumentNullException("match");
}
for each (PropertyInfo^ pi in match)
{
if (pi->GetType() == returnType &&
ParametersMatch(pi->GetIndexParameters(), indexes))
{
return pi;
}
}
return nullptr;
}
virtual Object^ ChangeType(
Object^ value,
Type^ myChangeType,
CultureInfo^ culture) override
{
try
{
Object^ newType;
newType = Convert::ChangeType(value, myChangeType);
return newType;
}
// Throw an InvalidCastException if the conversion cannot
// be done by the Convert.ChangeType method.
catch (InvalidCastException^)
{
return nullptr;
}
}
virtual void ReorderArgumentArray(array<Object^>^% args,
Object^ state) override
{
// No operation is needed here because BindToMethod does not
// reorder the args array. The most common implementation
// of this method is shown below.
// ((BinderState^)state).args.CopyTo(args, 0);
}
// Returns true only if the type of each object in a matches
// the type of each corresponding object in b.
private:
bool ParametersMatch(array<ParameterInfo^>^ a, array<Object^>^ b)
{
if (a->Length != b->Length)
{
return false;
}
for (int i = 0; i < a->Length; i++)
{
if (a[i]->ParameterType != b[i]->GetType())
{
return false;
}
}
return true;
}
// Returns true only if the type of each object in a matches
// the type of each corresponding entry in b.
bool ParametersMatch(array<ParameterInfo^>^ a, array<Type^>^ b)
{
if (a->Length != b->Length)
{
return false;
}
for (int i = 0; i < a->Length; i++)
{
if (a[i]->ParameterType != b[i])
{
return false;
}
}
return true;
}
};
public ref class MyMainClass
{
public:
static void Main()
{
// Get the type of MySimpleClass.
Type^ myType = MySimpleClass::typeid;
// Get an instance of MySimpleClass.
MySimpleClass^ myInstance = gcnew MySimpleClass();
MyCustomBinder^ myCustomBinder = gcnew MyCustomBinder();
// Get the method information for the particular overload
// being sought.
MethodInfo^ myMethod = myType->GetMethod("MyMethod",
BindingFlags::Public | BindingFlags::Instance,
myCustomBinder, gcnew array<Type^> {String::typeid,
int::typeid}, nullptr);
Console::WriteLine(myMethod->ToString());
// Invoke the overload.
myType->InvokeMember("MyMethod", BindingFlags::InvokeMethod,
myCustomBinder, myInstance,
gcnew array<Object^> {"Testing...", (int)32});
}
};
}
int main()
{
Custom_Binder::MyMainClass::Main();
}
// Code for building SimpleType.dll.
using System;
using System.Reflection;
using System.Globalization;
using Simple_Type;
namespace Simple_Type
{
public class MySimpleClass
{
public void MyMethod(string str, int i)
{
Console.WriteLine("MyMethod parameters: {0}, {1}", str, i);
}
public void MyMethod(string str, int i, int j)
{
Console.WriteLine("MyMethod parameters: {0}, {1}, {2}",
str, i, j);
}
}
}
namespace Custom_Binder
{
class MyMainClass
{
static void Main()
{
// Get the type of MySimpleClass.
Type myType = typeof(MySimpleClass);
// Get an instance of MySimpleClass.
MySimpleClass myInstance = new MySimpleClass();
MyCustomBinder myCustomBinder = new MyCustomBinder();
// Get the method information for the particular overload
// being sought.
MethodInfo myMethod = myType.GetMethod("MyMethod",
BindingFlags.Public | BindingFlags.Instance,
myCustomBinder, new Type[] {typeof(string),
typeof(int)}, null);
Console.WriteLine(myMethod.ToString());
// Invoke the overload.
myType.InvokeMember("MyMethod", BindingFlags.InvokeMethod,
myCustomBinder, myInstance,
new Object[] {"Testing...", (int)32});
}
}
// ****************************************************
// A simple custom binder that provides no
// argument type conversion.
// ****************************************************
class MyCustomBinder : Binder
{
public override MethodBase BindToMethod(
BindingFlags bindingAttr,
MethodBase[] match,
ref object[] args,
ParameterModifier[] modifiers,
CultureInfo culture,
string[] names,
out object state)
{
if (match == null)
{
throw new ArgumentNullException("match");
}
// Arguments are not being reordered.
state = null;
// Find a parameter match and return the first method with
// parameters that match the request.
foreach (MethodBase mb in match)
{
ParameterInfo[] parameters = mb.GetParameters();
if (ParametersMatch(parameters, args))
{
return mb;
}
}
return null;
}
public override FieldInfo BindToField(BindingFlags bindingAttr,
FieldInfo[] match, object value, CultureInfo culture)
{
if (match == null)
{
throw new ArgumentNullException("match");
}
foreach (FieldInfo fi in match)
{
if (fi.GetType() == value.GetType())
{
return fi;
}
}
return null;
}
public override MethodBase SelectMethod(
BindingFlags bindingAttr,
MethodBase[] match,
Type[] types,
ParameterModifier[] modifiers)
{
if (match == null)
{
throw new ArgumentNullException("match");
}
// Find a parameter match and return the first method with
// parameters that match the request.
foreach (MethodBase mb in match)
{
ParameterInfo[] parameters = mb.GetParameters();
if (ParametersMatch(parameters, types))
{
return mb;
}
}
return null;
}
public override PropertyInfo SelectProperty(
BindingFlags bindingAttr,
PropertyInfo[] match,
Type returnType,
Type[] indexes,
ParameterModifier[] modifiers)
{
if (match == null)
{
throw new ArgumentNullException("match");
}
foreach (PropertyInfo pi in match)
{
if (pi.GetType() == returnType &&
ParametersMatch(pi.GetIndexParameters(), indexes))
{
return pi;
}
}
return null;
}
public override object ChangeType(
object value,
Type myChangeType,
CultureInfo culture)
{
try
{
object newType;
newType = Convert.ChangeType(value, myChangeType);
return newType;
}
// Throw an InvalidCastException if the conversion cannot
// be done by the Convert.ChangeType method.
catch (InvalidCastException)
{
return null;
}
}
public override void ReorderArgumentArray(ref object[] args,
object state)
{
// No operation is needed here because BindToMethod does not
// reorder the args array. The most common implementation
// of this method is shown below.
// ((BinderState)state).args.CopyTo(args, 0);
}
// Returns true only if the type of each object in a matches
// the type of each corresponding object in b.
private bool ParametersMatch(ParameterInfo[] a, object[] b)
{
if (a.Length != b.Length)
{
return false;
}
for (int i = 0; i < a.Length; i++)
{
if (a[i].ParameterType != b[i].GetType())
{
return false;
}
}
return true;
}
// Returns true only if the type of each object in a matches
// the type of each corresponding entry in b.
private bool ParametersMatch(ParameterInfo[] a, Type[] b)
{
if (a.Length != b.Length)
{
return false;
}
for (int i = 0; i < a.Length; i++)
{
if (a[i].ParameterType != b[i])
{
return false;
}
}
return true;
}
}
}
' Code for building SimpleType.dll.
Imports System.Reflection
Imports System.Globalization
Imports Simple_Type
Namespace Simple_Type
Public Class MySimpleClass
Public Sub MyMethod(str As String, i As Integer)
Console.WriteLine("MyMethod parameters: {0}, {1}", str, i)
End Sub
Public Sub MyMethod(str As String, i As Integer, j As Integer)
Console.WriteLine("MyMethod parameters: {0}, {1}, {2}",
str, i, j)
End Sub
End Class
End Namespace
Namespace Custom_Binder
Class MyMainClass
Shared Sub Main()
' Get the type of MySimpleClass.
Dim myType As Type = GetType(MySimpleClass)
' Get an instance of MySimpleClass.
Dim myInstance As New MySimpleClass()
Dim myCustomBinder As New MyCustomBinder()
' Get the method information for the particular overload
' being sought.
Dim myMethod As MethodInfo = myType.GetMethod("MyMethod",
BindingFlags.Public Or BindingFlags.Instance,
myCustomBinder, New Type() {GetType(String),
GetType(Integer)}, Nothing)
Console.WriteLine(myMethod.ToString())
' Invoke the overload.
myType.InvokeMember("MyMethod", BindingFlags.InvokeMethod,
myCustomBinder, myInstance,
New Object() {"Testing...", CInt(32)})
End Sub
End Class
' ****************************************************
' A simple custom binder that provides no
' argument type conversion.
' ****************************************************
Class MyCustomBinder
Inherits Binder
Public Overrides Function BindToMethod(bindingAttr As BindingFlags,
match() As MethodBase, ByRef args As Object(),
modIfiers() As ParameterModIfier, culture As CultureInfo,
names() As String, ByRef state As Object) As MethodBase
If match is Nothing Then
Throw New ArgumentNullException("match")
End If
' Arguments are not being reordered.
state = Nothing
' Find a parameter match and return the first method with
' parameters that match the request.
For Each mb As MethodBase in match
Dim parameters() As ParameterInfo = mb.GetParameters()
If ParametersMatch(parameters, args) Then
Return mb
End If
Next mb
Return Nothing
End Function
Public Overrides Function BindToField(bindingAttr As BindingFlags,
match() As FieldInfo, value As Object, culture As CultureInfo) As FieldInfo
If match Is Nothing
Throw New ArgumentNullException("match")
End If
For Each fi As FieldInfo in match
If fi.GetType() = value.GetType() Then
Return fi
End If
Next fi
Return Nothing
End Function
Public Overrides Function SelectMethod(bindingAttr As BindingFlags,
match() As MethodBase, types() As Type,
modifiers() As ParameterModifier) As MethodBase
If match Is Nothing Then
Throw New ArgumentNullException("match")
End If
' Find a parameter match and return the first method with
' parameters that match the request.
For Each mb As MethodBase In match
Dim parameters() As ParameterInfo = mb.GetParameters()
If ParametersMatch(parameters, types) Then
Return mb
End If
Next mb
Return Nothing
End Function
Public Overrides Function SelectProperty(
bindingAttr As BindingFlags, match() As PropertyInfo,
returnType As Type, indexes() As Type,
modIfiers() As ParameterModIfier) As PropertyInfo
If match Is Nothing Then
Throw New ArgumentNullException("match")
End If
For Each pi As PropertyInfo In match
If pi.GetType() = returnType And
ParametersMatch(pi.GetIndexParameters(), indexes) Then
Return pi
End If
Next pi
Return Nothing
End Function
Public Overrides Function ChangeType(
value As Object,
myChangeType As Type,
culture As CultureInfo) As Object
Try
Dim newType As Object
newType = Convert.ChangeType(value, myChangeType)
Return newType
' Throw an InvalidCastException If the conversion cannot
' be done by the Convert.ChangeType method.
Catch
Return Nothing
End Try
End Function
Public Overrides Sub ReorderArgumentArray(ByRef args() As Object, state As Object)
' No operation is needed here because BindToMethod does not
' reorder the args array. The most common implementation
' of this method is shown below.
' ((BinderState)state).args.CopyTo(args, 0)
End Sub
' Returns true only If the type of each object in a matches
' the type of each corresponding object in b.
Private Overloads Function ParametersMatch(a() As ParameterInfo, b() As Object) As Boolean
If a.Length <> b.Length Then
Return false
End If
For i As Integer = 0 To a.Length - 1
If a(i).ParameterType <> b(i).GetType() Then
Return false
End If
Next i
Return true
End Function
' Returns true only If the type of each object in a matches
' the type of each corresponding enTry in b.
Private Overloads Function ParametersMatch(a() As ParameterInfo,
b() As Type) As Boolean
If a.Length <> b.Length Then
Return false
End If
For i As Integer = 0 To a.Length - 1
If a(i).ParameterType <> b(i)
Return false
End If
Next
Return true
End Function
End Class
End Namespace
InvokeMember および CreateInstance
型のメンバーを呼び出すには、Type.InvokeMember を使用します。 Activator.CreateInstance や Assembly.CreateInstance などのさまざまなクラスの CreateInstance
メソッドは、指定した型の新しいインスタンスを作成する InvokeMember
の特殊な形式です。 Binder
クラスは、これらのメソッドのオーバーロードの解決や引数の強制型変換に使用されます。
引数の強制変換 (型変換) とメンバー選択の可能な 3 つの組み合わせの例を次に示します。 ケース 1 では、引数の強制変換、またはメンバーの選択は必要ありません。 ケース 2 では、メンバーの選択のみが必要です。 ケース 3 では、引数の強制変換のみが必要です。
public ref class CustomBinderDriver
{
public:
static void Main()
{
Type^ t = CustomBinderDriver::typeid;
CustomBinder^ binder = gcnew CustomBinder();
BindingFlags flags = BindingFlags::InvokeMethod | BindingFlags::Instance |
BindingFlags::Public | BindingFlags::Static;
array<Object^>^ args;
// Case 1. Neither argument coercion nor member selection is needed.
args = gcnew array<Object^> {};
t->InvokeMember("PrintBob", flags, binder, nullptr, args);
// Case 2. Only member selection is needed.
args = gcnew array<Object^> {42};
t->InvokeMember("PrintValue", flags, binder, nullptr, args);
// Case 3. Only argument coercion is needed.
args = gcnew array<Object^> {"5.5"};
t->InvokeMember("PrintNumber", flags, binder, nullptr, args);
}
static void PrintBob()
{
Console::WriteLine("PrintBob");
}
static void PrintValue(long value)
{
Console::WriteLine("PrintValue({0})", value);
}
static void PrintValue(String^ value)
{
Console::WriteLine("PrintValue\"{0}\")", value);
}
static void PrintNumber(double value)
{
Console::WriteLine("PrintNumber ({0})", value);
}
};
int main()
{
CustomBinderDriver::Main();
}
public class CustomBinderDriver
{
public static void Main()
{
Type t = typeof(CustomBinderDriver);
CustomBinder binder = new CustomBinder();
BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Instance |
BindingFlags.Public | BindingFlags.Static;
object[] args;
// Case 1. Neither argument coercion nor member selection is needed.
args = new object[] {};
t.InvokeMember("PrintBob", flags, binder, null, args);
// Case 2. Only member selection is needed.
args = new object[] {42};
t.InvokeMember("PrintValue", flags, binder, null, args);
// Case 3. Only argument coercion is needed.
args = new object[] {"5.5"};
t.InvokeMember("PrintNumber", flags, binder, null, args);
}
public static void PrintBob()
{
Console.WriteLine("PrintBob");
}
public static void PrintValue(long value)
{
Console.WriteLine("PrintValue({0})", value);
}
public static void PrintValue(string value)
{
Console.WriteLine("PrintValue\"{0}\")", value);
}
public static void PrintNumber(double value)
{
Console.WriteLine("PrintNumber ({0})", value);
}
}
Public Class CustomBinderDriver
Public Shared Sub Main()
Dim t As Type = GetType(CustomBinderDriver)
Dim binder As New CustomBinder()
Dim flags As BindingFlags = BindingFlags.InvokeMethod Or BindingFlags.Instance Or
BindingFlags.Public Or BindingFlags.Static
Dim args() As Object
' Case 1. Neither argument coercion nor member selection is needed.
args = New object() {}
t.InvokeMember("PrintBob", flags, binder, Nothing, args)
' Case 2. Only member selection is needed.
args = New object() {42}
t.InvokeMember("PrintValue", flags, binder, Nothing, args)
' Case 3. Only argument coercion is needed.
args = New object() {"5.5"}
t.InvokeMember("PrintNumber", flags, binder, Nothing, args)
End Sub
Public Shared Sub PrintBob()
Console.WriteLine("PrintBob")
End Sub
Public Shared Sub PrintValue(value As Long)
Console.WriteLine("PrintValue ({0})", value)
End Sub
Public Shared Sub PrintValue(value As String)
Console.WriteLine("PrintValue ""{0}"")", value)
End Sub
Public Shared Sub PrintNumber(value As Double)
Console.WriteLine("PrintNumber ({0})", value)
End Sub
End Class
オーバーロード解決は、同じ名前のメンバーを複数使用できる場合に必要です。 Binder.BindToMethod メソッドと Binder.BindToField メソッドは、単一のメンバーへのバインドの解決に使用します。 Binder.BindToMethod
は、get
と set
プロパティ アクセサーを介したプロパティ解決も提供します。
BindToMethod
は、呼び出す MethodBase を返します。そのような呼び出しが不可能な場合は null 参照 (Visual Basic ではNothing
) を返します。 これは通常のケースですが、MethodBase
の戻り値は、match パラメーターに含まれる値の 1 つである必要はありません。
ByRef 引数が存在する場合、呼び出し元はそれらを取得することが必要な場合があります。 したがって、BindToMethod
が引数配列を操作した場合、Binder
ではクライアントが引数配列を元の形態にマップし直すことができます。 これを行うには、呼び出し元は引数の順序が変わっていないことが保証される必要があります。 引数が名前によって渡されるとき、Binder
は呼び出し元が参照する引数配列の順序を変更します。 詳細については、Binder.ReorderArgumentArrayを参照してください。
利用可能なメンバーのセットは、その型と任意の基本型に定義されているメンバーです。 BindingFlags を指定すると、アクセシビリティのメンバーがセットに返されます。 BindingFlags.NonPublic
を指定しない場合、バインダーはアクセシビリティ規則を適用する必要があります。 Public
または NonPublic
のバインディング フラグを指定した場合、Instance
または Static
バインディング フラグも指定しないと、メンバーは返されません。
指定した名前のメンバーが 1 人のみの場合、コールバックの必要はなく、バインディングはそのメソッドに対して行われます。 コード例のケース 1 は、この点を示しています。使用可能な PrintBob
メソッドは 1 つだけなので、コールバックは不要です。
利用可能なセットに複数のメンバーがある場合、これらすべてのメソッドは BindToMethod
に渡され、適切なメソッドが選択され返されます。 コード例のケース 2 では、PrintValue
というメソッドが 2 つあります。 BindToMethod
を呼び出すと、適切なメソッドが選択されます。
ChangeType は、実引数を選択されたメソッドの仮引数の型に変換する引数の強制変換 (型変換) を行います。 ChangeType
は、型が正確に一致した場合でも、すべての引数に対して呼び出されます。
コード例のケース 3 では、値が "5.5" の String
型の実際の引数が Double
型の仮引数を持つメソッドに渡されます。 呼び出しが成功するには、文字列値 "5.5" を倍精度浮動小数点値に変換する必要があります。 ChangeType
はこの変換を実行します。
ChangeType
は、次の表に示すように、無損失または拡大強制型変換のみを実行します。
変換元の型 | 変換後の型 |
---|---|
任意の型 | その基本型 |
任意の型 | 実装するインターフェイス |
Char | UInt16、UInt32、Int32、UInt64、Int64、Single、Double |
Byte | Char、UInt16、Int16、UInt32、Int32、UInt64、Int64、Single、Double |
SByte | Int16、Int32、Int64、Single、Double |
UInt16 | UInt32、Int32、UInt64、Int64、Single、Double |
Int16 | Int32、Int64、Single、Double |
UInt32 | UInt64、Int64、Single、Double |
Int32 | Int64、Single、Double |
UInt64 | Single、Double |
Int64 | Single、Double |
Single | Double |
非参照型 | 参照型 |
Type クラスには、特定のメンバーへの参照を解決するために Binder
型のパラメーターを使用する Get
メソッドがあります。 Type.GetConstructor、Type.GetMethod、および Type.GetProperty は、現在の型の特定のメンバーに関するシグネチャ情報を提供して、そのメンバーを検索します。 該当するメソッドの指定されたシグネチャ情報を選択するために、Binder.SelectMethod および Binder.SelectProperty がコールバックされます。
関連項目
.NET