System.Delegate.CreateDelegate 方法 (Type, Object, MethodInfo, Boolean)
方法描述
使用指定的第一个参数和针对绑定失败的指定行为,创建表示指定的静态方法或实例方法的指定类型的委托。
语法定义(C# System.Delegate.CreateDelegate 方法 (Type, Object, MethodInfo, Boolean) 的用法)
public static Delegate CreateDelegate( Type type, Object firstArgument, MethodInfo method, bool throwOnBindFailure )
参数/返回值
参数值/返回值 | 参数类型/返回类型 | 参数描述/返回描述 |
---|---|---|
type | System-Type | 一个 Type,表示要创建的委托的类型。 |
firstArgument | System-Object | 一个 Object,它是委托表示的方法的第一个参数。对于实例方法,它必须与实例类型兼容。 |
method | System-Reflection-MethodInfo | 描述委托要表示的静态或实例方法的 MethodInfo。 |
throwOnBindFailure | System-Boolean | 为 true,表示无法绑定 method 时引发异常;否则为 false。 |
返回值 | System.Delegate | 表示指定的静态方法或实例方法的指定类型的委托,如果 throwOnBindFailure 为 false,并且委托无法绑定到 method,则为 null。 |
提示和注释
此方法重载和 CreateDelegate(Type, Object, MethodInfo) 方法重载(后者在绑定失败时始终引发异常)提供非常灵活的用于创建委托的方式。 可以使用这两种方法重载创建静态方法或实例方法的委托,可以提供也可以不提供第一个参数。
注意
如果不提供第一个参数,则使用 CreateDelegate(Type, MethodInfo, Boolean) 方法重载以获得更好的性能。
委托类型和方法必须具有兼容的返回类型。 即,method 的返回类型必须可以分配给 type 的返回类型。
如果提供了 firstArgument,则在每次调用委托时将其传递给 method;firstArgument 被称为绑定到委托,而委托被称为通过其第一个参数封闭。 如果 method 为 static(在 Visual Basic 中为 Shared),则调用委托时提供的参数列表包括除第一个参数以外的所有参数;如果 method 为实例方法,则 firstArgument 被传递给隐藏的实例参数(在 C# 中由 this 表示,在 Visual Basic 中由 Me 表示)。
如果提供了 firstArgument,则 method 的第一个参数必须为引用类型,并且 firstArgument 必须与该类型兼容。
重要事项
如果 method 为 static(在 Visual Basic 中为 Shared)并且其第一个参数的类型为 Object 或 ValueType,则 firstArgument 可以为值类型。 在这种情况下,firstArgument 会自动装箱。 与在 C# 或 Visual Basic 函数调用中不同,任何其他参数都不会发生自动装箱。
如果 firstArgument 为空引用并且 method 为实例方法,则结果取决于委托类型 type 的签名和 method 的签名:
如果 type 的签名显式包括 method 的第一个隐藏参数,则委托被称为表示开放的实例方法。 调用委托时,参数列表中的第一个参数被传递给 method 的隐藏实例参数。
如果 method 和 type 的签名匹配(即,所有参数类型都兼容),则委托被称为通过空引用封闭。 调用委托类似于对空实例调用实例方法,执行此操作不是特别有用。
如果 firstArgument 为空引用并且 method 为静态方法,则结果取决于委托类型 type 的签名和 method 的签名:
如果 method 和 type 的签名匹配(即,所有参数类型都兼容),则委托被称为表示开放的静态方法。 这是静态方法最常见的情况。 在这种情况下,可以使用 CreateDelegate(Type, MethodInfo, Boolean) 方法重载获得略优的性能。
如果 type 的签名以 method 的第二个参数开头,并且其余参数类型均兼容,则委托被称为通过空引用封闭。 调用委托时,空引用被传递给 method 的第一个参数。
注意
从 .NET Framework 2.0 版 Service Pack 1 开始,如果已授予调用方带有 ReflectionPermissionFlag.RestrictedMemberAccess 标志的 ReflectionPermission,并且非公共方法的授予集限制为调用方的授予集或其子集,则此方法可用于访问非公共方法。 (请参见 反射的安全注意事项。)
若要使用此功能,您的应用程序应面向 .NET Framework 3.5 版 或更高版本。
兼容的参数类型和返回类型
委托的参数类型和返回类型必须与委托所表示的方法的参数类型和返回类型兼容;但类型不必精确匹配。
注意
在 .NET Framework 1.0 和 1.1 版中,类型必须精确匹配。
如果委托参数的类型的限制性强于方法参数的类型,则该委托的参数与该方法的相应参数兼容,因为这可保证传递给委托的参数可以安全地传递给方法。
同样,如果方法的返回类型的限制性强于委托的返回类型,则该委托的返回类型与该方法的返回类型兼容,因为这可保证方法的返回值可以安全地强制转换为委托的返回类型。
例如,具有类型为 Hashtable 的参数和 Object 返回类型的委托可以表示具有类型为 Object 的参数和类型为 Hashtable 的返回值的方法。
确定委托可以表示的方法
CreateDelegate 的此重载所提供的灵活性还表现在任何给定的委托都可以表示方法签名和方法种类(静态与实例)的四种不同组合。 考虑具有一个 C 类型参数的 D 委托类型。 下面描述 D 可以表示的方法,忽略返回类型,因为返回类型在所有情况下都必须匹配:
D 可以表示任何仅具有一个 C 类型的参数的实例方法,与实例方法所属的类型无关。 调用 CreateDelegate 时,firstArgument 是 method 所属类型的实例,并且结果委托被称为通过该实例封闭。 (一般而言,如果 firstArgument 为 null,则 D 还可以通过空引用封闭。)
D 可以表示没有参数的 C 的实例方法。 调用 CreateDelegate 时,firstArgument 为空引用。 结果委托表示开放的实例方法,并且每次调用时都必须提供 C 的实例。
D 可以表示采用一个 C 类型的参数的静态方法,并且该方法可以属于任何类型。 调用 CreateDelegate 时,firstArgument 为空引用。 结果委托表示开放的静态方法,并且每次调用时都必须提供 C 的实例。
D 可以表示一个属于 F 类型的静态方法,并且有两个参数,分别为 F 类型和 C 类型。 调用 CreateDelegate 时,firstArgument 为 F 的实例。 结果委托表示通过 F 的该实例封闭的静态方法。 注意,当 F 和 C 为相同类型时,静态方法具有两个该类型的参数。 (在这种情况下,如果 firstArgument 为 null,则 D 通过空引用封闭。)
System.Delegate.CreateDelegate 方法 (Type, Object, MethodInfo, Boolean)例子
C 类型的方法 M4 显示绑定实例和参数的 ID 属性。
using System; using System.Reflection; using System.Security.Permissions; // Declare a delegate type. The object of this code example // is to show all the methods this delegate can bind to. // public delegate void D(C c); // Declare two sample classes, C and F. Class C has an ID // property so instances can be identified. // public class C { private int id; public int ID { get { return id; }} public C(int id) { this.id = id; } public void M1(C c) { Console.WriteLine("Instance method M1(C c) on C: this.id = {0}, c.ID = {1}", this.id, c.ID); } public void M2() { Console.WriteLine("Instance method M2() on C: this.id = {0}", this.id); } public static void M3(C c) { Console.WriteLine("Static method M3(C c) on C: c.ID = {0}", c.ID); } public static void M4(C c1, C c2) { Console.WriteLine("Static method M4(C c1, C c2) on C: c1.ID = {0}, c2.ID = {1}", c1.ID, c2.ID); } } public class F { public void M1(C c) { Console.WriteLine("Instance method M1(C c) on F: c.ID = {0}", c.ID); } public static void M3(C c) { Console.WriteLine("Static method M3(C c) on F: c.ID = {0}", c.ID); } public static void M4(F f, C c) { Console.WriteLine("Static method M4(F f, C c) on F: c.ID = {0}", c.ID); } } public class Example { public static void Main() { C c1 = new C(42); C c2 = new C(1491); F f1 = new F(); D d; // Instance method with one argument of type C. MethodInfo cmi1 = typeof(C).GetMethod("M1"); // Instance method with no arguments. MethodInfo cmi2 = typeof(C).GetMethod("M2"); // Static method with one argument of type C. MethodInfo cmi3 = typeof(C).GetMethod("M3"); // Static method with two arguments of type C. MethodInfo cmi4 = typeof(C).GetMethod("M4"); // Instance method with one argument of type C. MethodInfo fmi1 = typeof(F).GetMethod("M1"); // Static method with one argument of type C. MethodInfo fmi3 = typeof(F).GetMethod("M3"); // Static method with an argument of type F and an argument // of type C. MethodInfo fmi4 = typeof(F).GetMethod("M4"); Console.WriteLine("\nAn instance method on any type, with an argument of type C."); // D can represent any instance method that exactly matches its // signature. Methods on C and F are shown here. // d = (D) Delegate.CreateDelegate(typeof(D), c1, cmi1); d(c2); d = (D) Delegate.CreateDelegate(typeof(D), f1, fmi1); d(c2); Console.WriteLine("\nAn instance method on C with no arguments."); // D can represent an instance method on C that has no arguments; // in this case, the argument of D represents the hidden first // argument of any instance method. The delegate acts like a // static method, and an instance of C must be passed each time // it is invoked. // d = (D) Delegate.CreateDelegate(typeof(D), null, cmi2); d(c1); Console.WriteLine("\nA static method on any type, with an argument of type C."); // D can represent any static method with the same signature. // Methods on F and C are shown here. // d = (D) Delegate.CreateDelegate(typeof(D), null, cmi3); d(c1); d = (D) Delegate.CreateDelegate(typeof(D), null, fmi3); d(c1); Console.WriteLine("\nA static method on any type, with an argument of"); Console.WriteLine(" that type and an argument of type C."); // D can represent any static method with one argument of the // type the method belongs and a second argument of type C. // In this case, the method is closed over the instance of // supplied for the its first argument, and acts like an instance // method. Methods on F and C are shown here. // d = (D) Delegate.CreateDelegate(typeof(D), c1, cmi4); d(c2); Delegate test = Delegate.CreateDelegate(typeof(D), f1, fmi4, false); // This final example specifies false for throwOnBindFailure // in the call to CreateDelegate, so the variable 'test' // contains Nothing if the method fails to bind (for // example, if fmi4 happened to represent a method of // some class other than F). // if (test != null) { d = (D) test; d(c2); } } } /* This code example produces the following output: An instance method on any type, with an argument of type C. Instance method M1(C c) on C: this.id = 42, c.ID = 1491 Instance method M1(C c) on F: c.ID = 1491 An instance method on C with no arguments. Instance method M2() on C: this.id = 42 A static method on any type, with an argument of type C. Static method M3(C c) on C: c.ID = 42 Static method M3(C c) on F: c.ID = 42 A static method on any type, with an argument of that type and an argument of type C. Static method M4(C c1, C c2) on C: c1.ID = 42, c2.ID = 1491 Static method M4(F f, C c) on F: c.ID = 1491 */
异常
异常 | 异常描述 |
---|---|
ArgumentNullException |
|
ArgumentException |
|
MissingMethodException | 未找到 type 的 Invoke 方法。 |
MethodAccessException | 调用方无权访问 method。 |
版本信息
.NET Framework 受以下版本支持:4、3.5、3.0、2.0 .NET Framework Client Profile 受以下版本支持:4、3.5 SP1
适用平台
Windows 7, Windows Vista SP1 或更高版本, Windows XP SP3, Windows XP SP2 x64 Edition, Windows Server 2008(不支持服务器核心), Windows Server 2008 R2(支持 SP1 或更高版本的服务器核心), Windows Server 2003 SP2 .NET Framework 并不是对每个平台的所有版本都提供支持。有关支持的版本的列表,请参见.NET Framework 系统要求。