تحميله ديناميكياً و استخدام أنواع
انعكاس provides infrastructure used بواسطة اللغة compilers such كـ Microsoft Visual Basic 2005 و JScript إلى implement implicit ربط في وقت التشغيل. ربط هو the عملية of locating the إعلان (that هو, the implementation) that corresponds إلى a uniquely specified نوع. عند ترتيب هو تحدث عملية في وقت التشغيل بدلاً من وقت التحويل البرمجي، هو تسمى ربط في وقت التشغيل. Visual Basic 2005يسمح لك إلى استخدام ربط المتأخر ضمني في تعليمات برمجية الخاصة بك؛ المحول البرمجي Visual أساسى استدعاء أسلوب مساعد الذي يستخدم انعكاس إلى الحصول على نوع كائن. الوسائط التي تم تمريرها إلى المساعد أسلوب تسبب المناسبة أسلوب لطلبة في وقت التشغيل. These الوسيطات are the مثيل (an كائن) تشغيل which إلى invoke the أسلوب, the اسم of the invoked أسلوب (a سلسلة), و the الوسيطات passed إلى the invoked أسلوب (an مصفوفه من الكائنات).
في the following مثال, the Visual أساسى compiler uses انعكاس ضمنيا إلى يتصل a أسلوب تشغيل an كائن whose نوع ليس known at يحول برمجياً الوقت. A HelloWorld فئة has a PrintHello أسلوب that prints خارج "Hello World" concatenated مع some نص that هو passed إلى the PrintHello أسلوب. الأسلوب PrفيtHello الذي يسمى في هذا المثال هو فعلياً على Type.InvokeMember; يسمح تعليمات برمجية Visual أساسى PrفيtHello الأسلوب طلبه كما لو كانت تعرف نوع الكائن (helloObj) في وقت التحويل البرمجي (ربط المبكر) وليس في وقت التشغيل (متأخر ربط).
Imports System
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
مخصص ربط
في addition إلى being used ضمنيا بواسطة compilers for ربط في وقت التشغيل, انعكاس can be used بوضوح في تعليمات برمجية إلى accomplish ربط في وقت التشغيل.
The وقت تشغيل اللغة العامة supports multiple programming languages, و the ربط rules of these languages differ. في the early-حدود حالة, تعليمات برمجية generators can completely عنصر تحكم this ربط. However, في ربط في وقت التشغيل through انعكاس, binding must be controlled بواسطة مخصص binding. The Binder فئة provides مخصص عنصر تحكم of عضو تحديد و invocation.
Using مخصص ربط, you can تحميل an تجميع at run الوقت, obtain معلومات حول أنواع في that تجميع, specify the نوع that you want, و then invoke وظائف أو الوصول حقول أو خصائص تشغيل that نوع. This technique هو useful if you do not know an كائن's نوع at يحول برمجياً الوقت, such كـ when the كائن نوع هو dependent تشغيل مستخدم إدخال.
The following مثال demonstrates a simple مخصص binder that provides لا وسيطة نوع تحويل. تعليمات برمجية for Simple_Type.dll precedes the main مثال. Be sure إلى بنية Simple_Type.dll و then تضمين a مرجع إلى it في the مشروع at بنية الوقت.
' Code for building Simple_Type.dll.
Imports System
Namespace Simple_Type
Public Class MySimpleClass
Public Overloads Sub MyMethod(ByVal str As String,
ByVal i As Integer)
Console.WriteLine("MyMethod parameters: {0}, {1}", str, i)
End Sub 'MyMethod
Public Overloads Sub MyMethod(ByVal str As String,
ByVal i As Integer, ByVal j As Integer)
Console.WriteLine("MyMethod parameters: {0}, {1}, {2}", str,
i, j)
End Sub 'MyMethod
End Class 'MySimpleClass
End Namespace 'Simple_Type
Imports System
Imports System.Reflection
Imports System.Globalization
Imports Simple_Type.Simple_Type
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 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 'Main
End Class 'MyMainClass
'****************************************************
' A simple custom binder that provides no
' argument type conversion.
'****************************************************
Class MyCustomBinder
Inherits Binder
Public Overrides Function BindToMethod(ByVal bindingAttr As
BindingFlags, ByVal match() As MethodBase, ByRef args() As
Object, ByVal modifiers() As ParameterModifier, ByVal
culture As CultureInfo, ByVal 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.
Dim mb As MethodBase
For Each mb In match
Dim parameters As ParameterInfo() = mb.GetParameters()
If ParametersMatch(parameters, args) Then
Return mb
End If
Next mb
Return Nothing
End Function 'BindToMethod
Public Overrides Function BindToField(ByVal bindingAttr As
BindingFlags, ByVal match() As FieldInfo, ByVal value As
Object, ByVal culture As CultureInfo) As FieldInfo
If match Is Nothing Then
Throw New ArgumentNullException("match")
End If
Dim fi As FieldInfo
For Each fi In match
If fi.GetType() Is value.GetType() Then
Return fi
End If
Next fi
Return Nothing
End Function 'BindToField
Public Overrides Function SelectMethod(ByVal bindingAttr As
BindingFlags, ByVal match() As MethodBase, ByVal types() As
Type, ByVal 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.
Dim mb As MethodBase
For Each mb In match
Dim parameters As ParameterInfo() = mb.GetParameters()
If ParametersMatch(parameters, types) Then
Return mb
End If
Next mb
Return Nothing
End Function 'SelectMethod
Public Overrides Function SelectProperty(ByVal bindingAttr As
BindingFlags, ByVal match() As PropertyInfo, ByVal returnType
As Type, ByVal indexes() As Type, ByVal modifiers() As
ParameterModifier) As PropertyInfo
If match Is Nothing Then
Throw New ArgumentNullException("match")
End If
Dim pi As PropertyInfo
For Each pi In match
If pi.GetType() Is returnType And
ParametersMatch(pi.GetIndexParameters(), indexes) Then
Return pi
End If
Next pi
Return Nothing
End Function 'SelectProperty
Public Overrides Function ChangeType(ByVal value As Object,
ByVal myChangeType As Type, ByVal 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
End Try
End Function 'ChangeType
Public Overrides Sub ReorderArgumentArray(ByRef args() As Object,
ByVal 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 'ReorderArgumentArray
' Returns true only if the type of each object in a matches
' the type of each corresponding object in b.
Private Overloads Function ParametersMatch(ByVal a() As
ParameterInfo, ByVal b() As Object) As Boolean
If a.Length <> b.Length Then
Return False
End If
Dim i As Integer
For i = 0 To a.Length - 1
If Not (a(i).ParameterType Is b(i).GetType()) Then
Return False
End If
Next i
Return True
End Function 'ParametersMatch
' Returns true only if the type of each object in a matches
' the type of each corresponding entry in b.
Private Overloads Function ParametersMatch(ByVal a() As
ParameterInfo, ByVal b() As Type) As Boolean
If a.Length <> b.Length Then
Return False
End If
Dim i As Integer
For i = 0 To a.Length - 1
If Not (a(i).ParameterType Is b(i)) Then
Return False
End If
Next i
Return True
End Function 'ParametersMatch
End Class 'MyCustomBinder
End Namespace 'Custom_Binder
// Code for building SimpleType.dll.
using System;
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);
}
}
}
using System;
using System.Reflection;
using System.Globalization;
using Simple_Type;
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;
}
}
}
InvokeMember و CreateInstance
استخدم Type.InvokeMember إلى invoke a عضو of a نوع. The CreateInstance وظائف of متنوع فئات, such كـ النظام.Activator و النظام.انعكاس.تجميع, are specialized forms of InvokeMember that إنشاء ارتباط جديد instances of the specified نوع. The Binder فئة هو used for التحميل الزائد دقة و وسيطة coercion في these وظائف.
يظهر المثال التالي التركيبات الممكنة الثلاثة من قسرية وسيطة (نوع تحويل) و تحديد الأعضاء. في "الحالة الأولى" أو لا تحديد عضو أو قسرية وسيطة هو المطلوبة. في "الحالة الثانية"، وتحديد الأعضاء فقط هو المطلوبة. في حالة 3، قسرية وسيطة فقط هو المطلوبة.
public class CustomBinderDriver
{
public static void Main (string[] arguments)
{
Type t = typeof (CustomBinderDriver);
CustomBinder binder = new CustomBinder();
BindingFlags flags = BindingFlags.InvokeMethod|BindingFlags.Instance|
BindingFlags.Public|BindingFlags.Static;
// 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);
}
}
حل زيادة التحميل هو الحاجة لوقت المزيد عضو واحد يحمل نفس الاسم هو المتوفرة. Binder.BindToMethodو Binder.BindToFieldالأساليب إلى حل ربط إلى عضو مفرد. Binder.BindToMethod أيضا توفير تحليل خاصية من خلال يحصل و التعيين accessors خاصية.
BindToMethod بإرجاع MethodBaseلاستدعاء، أو مرجع فارغ ( لا شيء في Vهوual أساسي) في حالة عدم وجود مثل هذا الاستدعاء هو المحتملة. من MethodBase بإرجاع يجب إلا تكون القيمة واحدة من تلك الموجودة في معلمة يطابق ، على الرغم من أن الذي هو الحالة العادية.
في حالة وجود وسيطات ByRef، قد تحتاج المتصل إلى لاسترداد. ولذلك، يسمح أوراق عميل لتعيين صفيفة الوسيطات الخلف إلى شكلها الأصلي إذا تم معالجته من BindToMethod صفيفة وسيطة. لكي تتمكن من القيام بترتيب هو، يجب أن يكون الطالب يمكن ضمان ترتيب الوسيطات هو بدون تغيير. حيث يتم تمرير الوسيطات حسب الاسم، reorders أوراق صفيفة وسيطة، وأن هو ما يراه الشخص المتصل. لمزيد من المعلومات، راجع Binder.ReorderArgumentArray.
مجموعة الأعضاء المتاحين قابلة لأعضاء تلك المعرفة في النوع أو أي الأساس نوع. إذا من BindingFlags.NonPublic هو، الأعضاء من أي وصول ذوي الاحتياجات الخاصة سيتم إرجاع في المجموعة. إذا من BindingFlags.NonPublic هو لم يكن محدداً، الموثق يجب فرض قواعد وصول ذوي الاحتياجات الخاصة. عند تحديد العام أو لا nPublic إشارة ربط ، يجب أيضا تحديد مثيل أو ثابتة التوثيق إشارة، أو لا سيتم إرجاع الأعضاء.
إذا كان هناك واحد فقط عضو في هذا الاسم، رد الاتصال غير ضروري، ويتم إجراء ربط تشغيل هذه الطريقة. حالة 1 تعليمات برمجية مثال يوضح هذه النقطة: واحد فقط PrintBob الطريقة هو المتوفرة، ولذلك لا يوجد رد هو المطلوبة.
إذا كان هناك هو أكثر من عضو في مجموعة متوفرة، يتم تمرير الجميع هذه الأساليب إلى BindToMethod ، الذي يحدد الطريقة المناسبة وإرجاعه. في "الحالة الثانية" من تعليمات برمجية المثال، توجد طريقتان باسم من PrintValue. الطريقة المناسبة هو المحددة من قبل الاستدعاء من BindToMethod.
ChangeTypeينفذ قسرية وسيطة (تحويل نوع)، والتي تقوم بتحويل الوسيطات الفعلية إلى نوع وسيطة رسمية للأسلوب المحدد. ChangeType هو استدعاء لكل وسيطة حتى في حالة تطابق الأنواع تماما.
في حالة كتابة 3 لمثال التعليمة البرمجية، وسيطة فعلية من سلسلةتحتوي على القيمة "5.5" هو الذي تم تمريره إلى أسلوب باستخدام وسيطة رسمية من نوع نوع بيانات مزدوج. الاستدعاء نجاح، يجب محول القيمة السلسلة "5.5" إلى القيمة مزدوجة. ChangeType تنفيذ هذا تحويل.
ChangeType ينفذ فقط بدون فقدان بيانات أو توسيع coercions ، كما هو موضح في الجدول التالي.
نوع المصدر |
نوع الهدف |
---|---|
أي نوع |
به أساس نوع |
أي نوع |
واجهة implements |
حرف |
UInt16 UInt32، Int32 أو UInt64، Int64، مفرد، مزدوج |
Byte (بايت) |
مفرد حرف، UInt16، Int16، UInt32، Int32، UInt64، Int64،، مزدوج |
SByte |
Int16، Int32، Int64، مفرد، مزدوج |
UInt16 |
UInt32 Int32 أو UInt64، Int64، مفرد، مزدوج |
Int16 |
Int32، Int64، مفرد، مزدوج |
UInt32 |
UInt64، Int64، مفرد، مزدوج |
Int32 |
Int64، مفرد، مزدوج |
UInt64 |
مفرد، مزدوج |
Int64 |
مفرد، مزدوج |
مفرد |
مزدوج |
نوع nonreference |
نوع المرجع |
Typeلدى فئة يحصل وظائف التي تستخدم المعلمات من نوع أوراق لحل المراجع إلى عضو محدد. Type.GetConstructor,Type.GetMethod، وType.GetPropertyبحث عن عضو معين من النوع الحالي بواسطة توفير معلومات توقيع لهذا العضو. Binder.SelectMethod and Binder.SelectProperty are called back on to select the given signature information of the appropriate methods.