Upravit

Sdílet prostřednictvím


<Method> Element (.NET Native)

Applies runtime reflection policy to a constructor or method.

Syntax

<Method Name="method_name"
        Signature="method_signature"
        Browse="policy_type"
        Dynamic="policy_type" />

Attributes and Elements

The following sections describe attributes, child elements, and parent elements.

Attributes

Attribute Attribute type Description
Name General Required attribute. Specifies the method name.
Signature General Optional attribute. Specifies the method signature. If multiple parameters are present, they are separated by commas. For example, the following <Method> element defines policy for the ToString(String, IFormatProvider) method.

<Type Name="System.DateTime"> <Method Name="ToString" Signature="System.String,System.IFormatProvider" Dynamic="Required" /> </Type>

If the attribute is absent, the runtime directive applies to all overloads of the method.
Browse Reflection Optional attribute. Controls querying for information about or enumerating a method but does not enable any dynamic invocation at run time.
Dynamic Reflection Optional attribute. Controls runtime access to a constructor or method to enable dynamic programming. This policy ensures that a member can be invoked dynamically at run time.

Name attribute

Value Description
method_name The method name. The type of the method is defined by the parent <Type> or <TypeInstantiation> element.

Signature attribute

Value Description
method_signature The parameter types that form the method signature. Multiple parameters are separated by commas, for example, "System.String,System.Int32,System.Int32)". Parameter type names should be fully qualified.

All other attributes

Value Description
policy_setting The setting to apply to this policy type. Possible values are Auto, Excluded, Included, and Required. For more information, see Runtime Directive Policy Settings.

Child Elements

Element Description
<Parameter> Applies policy to the type of the argument passed to a method.
<GenericParameter> Applies policy to the parameter type of a generic type or method.
<ImpliesType> Applies policy to a type, if that policy has been applied to the method represented by the containing <Method> element.
<TypeParameter> Applies policy to the type represented by a Type argument passed to a method.

Parent Elements

Element Description
<Type> Applies reflection policy to a type and all its members.
<TypeInstantiation> Applies reflection policy to a constructed generic type and all its members.

Remarks

A <Method> element of a generic method applies its policy to all instantiations that do not have their own policy.

You can use the Signature attribute to specify policy for a particular method overload. Otherwise, if the Signature attribute is absent, the runtime directive applies to all overloads of the method.

You cannot define the runtime reflection policy for a constructor by using the <Method> element. Instead, use the Activate attribute of the <Assembly>, <Namespace>, <Type>, or <TypeInstantiation> element.

Example

The Stringify method in the following example is a general-purpose formatting method that uses reflection to convert an object to its string representation. In addition to calling the object's default ToString method, the method can produce a formatted result string by passing an object's ToString method a format string, an IFormatProvider implementation, or both. It can also call one of the Convert.ToString overloads that converts a number to its binary, hexadecimal, or octal representation.

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;
   }
}

The Stringify method can be called by code like the following:

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;
   }
}

However, when compiled with .NET Native, the example can throw a number of exceptions at runtime, including NullReferenceException and MissingRuntimeArtifactException exceptions, This occurs because the Stringify method is intended primarily to support dynamically formatting the primitive types in the .NET Framework Class Library. However, their metadata is not made available by the default directives file. Even when their metadata is made available, however, the example throws MissingRuntimeArtifactException exceptions because the appropriate ToString implementations have not been include in the native code.

These exceptions can all be eliminated by using the <Type> element to define the types whose metadata must be present, and by adding <Method> elements to ensure that the implementation of method overloads that can be called dynamically is also present. The following is the default.rd.xml file that eliminates these exceptions and allows the example to execute without error.

<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>

See also