<Method> 元素 (.NET Native)
将运行时反射策略应用到一个构造函数或方法。
语法
<Method Name="method_name"
Signature="method_signature"
Browse="policy_type"
Dynamic="policy_type" />
特性和元素
下列各节描述了特性、子元素和父元素。
特性
属性 | 属性类型 | 说明 |
---|---|---|
Name |
常规 | 必需的特性。 指定方法名称。 |
Signature |
常规 | 可选特性。 指定方法签名。 如果存在多个参数,它们之间用逗号分割。 例如,以下 <Method> 元素定义了 ToString(String, IFormatProvider) 方法的策略。<Type Name="System.DateTime"> <Method Name="ToString" Signature="System.String,System.IFormatProvider" Dynamic="Required" /> </Type> 如果该特性不存在,运行时指令将应用到该方法的所有重载。 |
Browse |
反射 | 可选特性。 控制对该方法信息的查询或列举该方法,但并不在运行时间启用任何动态调用。 |
Dynamic |
反射 | 可选特性。 控制运行时对构造函数或方法的访问,以启用动态编程。 该策略确保一个成员可在运行时间内得到调用。 |
Name 特性
Value | 说明 |
---|---|
method_name | 方法名称。 该方法的类型由父 <Type> 或 <TypeInstantiation> 元素定义。 |
签名特性
值 | 说明 |
---|---|
method_signature | 形成方法签名的参数类型。 多个参数由逗号分隔,例如,"System.String,System.Int32,System.Int32)" 。 参数类型名称应是完全限定的。 |
所有其他特性
Value | 说明 |
---|---|
策略_设置 | 该设置将应用到这种策略类型。 可能值为 Auto 、Excluded 、Included 和 Required 。 有关详细信息,请参阅运行时指令策略设置。 |
子元素
元素 | 说明 |
---|---|
<参数> | 将策略应用到传递到方法的参数类型。 |
<泛型参数> | 将策略应用到一个泛型类型或方法的参数类型。 |
<ImpliesType> | 如果该策略已应用到以包含 <Method> 元素为代表的方法,将该策略应用到一个类型。 |
<TypeParameter> | 将策略应用到以传递到方法为代表的 Type 自变量类型。 |
父元素
元素 | 说明 |
---|---|
<类型> | 将反射策略应用到一种类型及其所有成员。 |
<TypeInstantiation> | 将反射策略应用到一种构造泛型类型及其所有成员。 |
注解
一个泛型方法的 <Method>
元素会将其策略应用到所有不具有自身策略的实例化。
你可以使用 Signature
特性为特定的方法重载指定策略。 如果 Signature
特性不存在,运行时指令将应用到该方法的所有重载。
你无法通过使用 <Method>
元素为一个构造函数定义运行时反射策略。 相反,使用 <Assembly>、<Namespace>、<Type> 或 <TypeInstantiation> 元素的 Activate
特性。
示例
以下实例中的 Stringify
方法是使用反射将一个对象转化为其字符串表示形式的一个通用格式化方法。 除调用该对象的默认 ToString
方法外,该方法可以通过穿过一个对象的 ToString
方法格式字符车产生一个格式化的字符串或/和一个 IFormatProvider 实现。 它也可以调用将一个成员转化为其二进制、十六进制或八进制表示的 Convert.ToString 重载之一。
public class Stringify
{
public static string ConvertToString(Object[] obj)
{
if (obj == null)
throw new NullReferenceException("The obj parameter cannot be null.");
if (obj.Length == 0) return String.Empty;
if (obj[0].GetType() == typeof(String))
return obj[0] as string;
if (obj.Length == 1) return obj[0].ToString();
if (obj.Length > 3)
throw new ArgumentOutOfRangeException("The array can have from zero to three elements.");
string retval = "";
// Parameters indicate either a format specifier, numeric base, or format provider,
// or a format specifier with an IFormatProvider.
// A string as the first parameter indicates a format specifier.
if (obj[1].GetType() == typeof(String)) {
Type t = obj[0].GetType();
if (obj.Length == 2)
{
MethodInfo m = t.GetRuntimeMethod("ToString", new Type[] { typeof(String) });
retval = m.Invoke(obj[0], new object[] { obj[1] }).ToString();
}
else
{
MethodInfo m = t.GetRuntimeMethod("ToString", new Type[] { typeof(String), obj[2].GetType() });
retval = m.Invoke(obj[0], new object[] { obj[1], obj[2] }).ToString();
}
}
else if (obj[1] is IFormatProvider)
{
Type t = obj[0].GetType();
MethodInfo m = t.GetRuntimeMethod("ToString", new Type[] { obj[1].GetType() } );
retval = m.Invoke(obj[0], new object[] { obj[1] }).ToString();
}
// The second parameter is a base, so call Convert.ToString(number, int).
else {
Type t = typeof(Convert);
MethodInfo m = t.GetRuntimeMethod("ToString", new Type[] { obj[0].GetType(), obj[1].GetType() } );
retval = m.Invoke(null, obj).ToString();
}
return retval;
}
}
Stringify
方法可以通过类似以下的代码调用:
public class Stringify
{
public static string ConvertToString(Object[] obj)
{
if (obj == null)
throw new NullReferenceException("The obj parameter cannot be null.");
if (obj.Length == 0) return String.Empty;
if (obj[0].GetType() == typeof(String))
return obj[0] as string;
if (obj.Length == 1) return obj[0].ToString();
if (obj.Length > 3)
throw new ArgumentOutOfRangeException("The array can have from zero to three elements.");
string retval = "";
// Parameters indicate either a format specifier, numeric base, or format provider,
// or a format specifier with an IFormatProvider.
// A string as the first parameter indicates a format specifier.
if (obj[1].GetType() == typeof(String)) {
Type t = obj[0].GetType();
if (obj.Length == 2)
{
MethodInfo m = t.GetRuntimeMethod("ToString", new Type[] { typeof(String) });
retval = m.Invoke(obj[0], new object[] { obj[1] }).ToString();
}
else
{
MethodInfo m = t.GetRuntimeMethod("ToString", new Type[] { typeof(String), obj[2].GetType() });
retval = m.Invoke(obj[0], new object[] { obj[1], obj[2] }).ToString();
}
}
else if (obj[1] is IFormatProvider)
{
Type t = obj[0].GetType();
MethodInfo m = t.GetRuntimeMethod("ToString", new Type[] { obj[1].GetType() } );
retval = m.Invoke(obj[0], new object[] { obj[1] }).ToString();
}
// The second parameter is a base, so call Convert.ToString(number, int).
else {
Type t = typeof(Convert);
MethodInfo m = t.GetRuntimeMethod("ToString", new Type[] { obj[0].GetType(), obj[1].GetType() } );
retval = m.Invoke(null, obj).ToString();
}
return retval;
}
}
但是,使用 .NET Native 编译时,该示例可以在运行时引发许多异常,包括NullReferenceException和 MissingRuntimeArtifactException 异常,这是因为Stringify
该方法主要用于支持动态格式化 .NET Framework 类库中的基元类型。 然而,它们的元数据不会通过默认指令文件变得可以使用。 即使在它们的元数据变得可用时,实例还会引发 MissingRuntimeArtifactException 异常,因为适当的 ToString
实现并未包含在本机代码之中。
可通过使用 <Type> 元素来定义那些元数据必须存在的类型和添加 <Method>
元素来清除这些异常,从而确保可以动态调用的方法重载的实现也存在。 以下的 default.rd.xml 文件可以清除这些异常并允许实例没有错误地执行。
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="*Application*" Dynamic="Required All" />
<Type Name = "System.Convert" Browse="Required Public" Dynamic="Required Public" >
<Method Name="ToString" Dynamic ="Required" />
</Type>
<Type Name="System.Double" Browse="Required Public">
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name ="System.Int32" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name ="System.Int64" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Namespace Name="System" >
<Type Name="Byte" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name="DateTime" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name="Decimal" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name="Guid" Browse ="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name="Int16" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name="SByte" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name="Single" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name="TimeSpan" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name="UInt16" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name="UInt32" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
<Type Name="UInt64" Browse="Required Public" >
<Method Name="ToString" Dynamic="Required" />
</Type>
</Namespace>
</Application>
</Directives>