使用英语阅读

通过


如何:将程序集加载到仅反射上下文中

通过仅反射加载上下文,可检查为其他平台或 .NET 的其他版本编译的程序集。 只能检查而不能执行加载到此上下文中的代码。 这意味着无法创建对象,因为无法执行构造函数。 因为该代码无法执行,所以不会自动加载依赖项。 如果需要对依赖项进行检查,必须自行加载。

将程序集加载到仅反射加载上下文中

  1. 使用 ReflectionOnlyLoad(String) 方法重载可加载给定了显示名称的程序集,而使用 ReflectionOnlyLoadFrom 方法可加载给定了路径的程序集。 如果该程序集为二进制文件映像,则使用 ReflectionOnlyLoad(Byte[]) 方法重载。

    备注

    不能使用仅反射上下文从与执行上下文中的 .NET Framework 不同的版本加载 mscorlib.dll 版本。

  2. 如果该程序集具有依赖项,ReflectionOnlyLoad 方法不会加载这些依赖项。 如果需要对依赖项进行检查,必须自行加载。

  3. 使用程序集的 ReflectionOnly 属性确定是否已将程序集加载到仅反射上下文中。

  4. 如果向程序集或程序集中的类型应用了特性,则应使用 CustomAttributeData 类检查这些特性,确保未尝试在仅反射上下文中执行代码。 使用 CustomAttributeData.GetCustomAttributes 方法的适当重载获取表示应用于程序集、成员、模块或参数的特性的 CustomAttributeData 对象。

    备注

    应用于程序集或其内容的特性可能是在该程序集中定义的,也可能是在加载到仅反射上下文中的另一个程序集中定义的。 无法事先知悉这些特性是在何处定义的。

示例

以下代码示例演示如何检查应用于加载到仅反射上下文中的程序集的特性。

本代码示例定义带有两个构造函数和一个属性的自定义特性。 该特性可应用于程序集、在该程序集中声明的类型、该类型的方法以及该方法的参数。 执行时,该程序集将其本身加载到仅反射上下文中,并显示应用到程序集及其所含类型和成员的自定义特性的相关信息。

备注

为简化本代码示例,该程序集自行完成加载和检查操作。 通常情况下,不要在执行上下文和仅反射上下文中加载同一程序集。

using System;
using System.Reflection;
using System.Collections.Generic;
using System.Collections.ObjectModel;

// The example attribute is applied to the assembly.
[assembly:Example(ExampleKind.ThirdKind, Note="This is a note on the assembly.")]

// An enumeration used by the ExampleAttribute class.
public enum ExampleKind
{
    FirstKind,
    SecondKind,
    ThirdKind,
    FourthKind
};

// An example attribute. The attribute can be applied to all
// targets, from assemblies to parameters.
//
[AttributeUsage(AttributeTargets.All)]
public class ExampleAttribute : Attribute
{
    // Data for properties.
    private ExampleKind kindValue;
    private string noteValue;
    private string[] arrayStrings;
    private int[] arrayNumbers;

    // Constructors. The parameterless constructor (.ctor) calls
    // the constructor that specifies ExampleKind and an array of
    // strings, and supplies the default values.
    //
    public ExampleAttribute(ExampleKind initKind, string[] initStrings)
    {
        kindValue = initKind;
        arrayStrings = initStrings;
    }
    public ExampleAttribute(ExampleKind initKind) : this(initKind, null) {}
    public ExampleAttribute() : this(ExampleKind.FirstKind, null) {}

    // Properties. The Note and Numbers properties must be read/write, so they
    // can be used as named parameters.
    //
    public ExampleKind Kind { get { return kindValue; }}
    public string[] Strings { get { return arrayStrings; }}
    public string Note
    {
        get { return noteValue; }
        set { noteValue = value; }
    }
    public int[] Numbers
    {
        get { return arrayNumbers; }
        set { arrayNumbers = value; }
    }
}

// The example attribute is applied to the test class.
//
[Example(ExampleKind.SecondKind,
         new string[] { "String array argument, line 1",
                        "String array argument, line 2",
                        "String array argument, line 3" },
         Note="This is a note on the class.",
         Numbers = new int[] { 53, 57, 59 })]
public class Test
{
    // The example attribute is applied to a method, using the
    // parameterless constructor and supplying a named argument.
    // The attribute is also applied to the method parameter.
    //
    [Example(Note="This is a note on a method.")]
    public void TestMethod([Example] object arg) { }

    // Main() gets objects representing the assembly, the test
    // type, the test method, and the method parameter. Custom
    // attribute data is displayed for each of these.
    //
    public static void Main()
    {
        Assembly asm = Assembly.ReflectionOnlyLoad("Source");
        Type t = asm.GetType("Test");
        MethodInfo m = t.GetMethod("TestMethod");
        ParameterInfo[] p = m.GetParameters();

        Console.WriteLine($"\r\nAttributes for assembly: '{asm}'");
        ShowAttributeData(CustomAttributeData.GetCustomAttributes(asm));
        Console.WriteLine($"\r\nAttributes for type: '{t}'");
        ShowAttributeData(CustomAttributeData.GetCustomAttributes(t));
        Console.WriteLine($"\r\nAttributes for member: '{m}'");
        ShowAttributeData(CustomAttributeData.GetCustomAttributes(m));
        Console.WriteLine($"\r\nAttributes for parameter: '{p}'");
        ShowAttributeData(CustomAttributeData.GetCustomAttributes(p[0]));
    }

    private static void ShowAttributeData(
        IList<CustomAttributeData> attributes)
    {
        foreach( CustomAttributeData cad in attributes )
        {
            Console.WriteLine($"   {cad}");
            Console.WriteLine($"      Constructor: '{cad.Constructor}'");

            Console.WriteLine("      Constructor arguments:");
            foreach( CustomAttributeTypedArgument cata
                in cad.ConstructorArguments )
            {
                ShowValueOrArray(cata);
            }

            Console.WriteLine("      Named arguments:");
            foreach( CustomAttributeNamedArgument cana
                in cad.NamedArguments )
            {
                Console.WriteLine($"         MemberInfo: '{cana.MemberInfo}'");
                ShowValueOrArray(cana.TypedValue);
            }
        }
    }

    private static void ShowValueOrArray(CustomAttributeTypedArgument cata)
    {
        if (cata.Value.GetType() == typeof(ReadOnlyCollection<CustomAttributeTypedArgument>))
        {
            Console.WriteLine($"         Array of '{cata.ArgumentType}':");

            foreach (CustomAttributeTypedArgument cataElement in
                (ReadOnlyCollection<CustomAttributeTypedArgument>) cata.Value)
            {
                Console.WriteLine($"             Type: '{cataElement.ArgumentType}'  Value: '{cataElement.Value}'");
            }
        }
        else
        {
            Console.WriteLine($"         Type: '{cata.ArgumentType}'  Value: '{cata.Value}'");
        }
    }
}

/* This code example produces output similar to the following:

Attributes for assembly: 'source, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
   [System.Runtime.CompilerServices.CompilationRelaxationsAttribute((Int32)8)]
      Constructor: 'Void .ctor(Int32)'
      Constructor arguments:
         Type: 'System.Int32'  Value: '8'
      Named arguments:
   [System.Runtime.CompilerServices.RuntimeCompatibilityAttribute(WrapNonExceptionThrows = True)]
      Constructor: 'Void .ctor()'
      Constructor arguments:
      Named arguments:
         MemberInfo: 'Boolean WrapNonExceptionThrows'
         Type: 'System.Boolean'  Value: 'True'
   [ExampleAttribute((ExampleKind)2, Note = "This is a note on the assembly.")]
      Constructor: 'Void .ctor(ExampleKind)'
      Constructor arguments:
         Type: 'ExampleKind'  Value: '2'
      Named arguments:
         MemberInfo: 'System.String Note'
         Type: 'System.String'  Value: 'This is a note on the assembly.'

Attributes for type: 'Test'
   [ExampleAttribute((ExampleKind)1, new String[3] { "String array argument, line 1", "String array argument, line 2", "String array argument, line 3" }, Note = "This is a note on the class.", Numbers = new Int32[3] { 53, 57, 59 })]
      Constructor: 'Void .ctor(ExampleKind, System.String[])'
      Constructor arguments:
         Type: 'ExampleKind'  Value: '1'
         Array of 'System.String[]':
             Type: 'System.String'  Value: 'String array argument, line 1'
             Type: 'System.String'  Value: 'String array argument, line 2'
             Type: 'System.String'  Value: 'String array argument, line 3'
      Named arguments:
         MemberInfo: 'System.String Note'
         Type: 'System.String'  Value: 'This is a note on the class.'
         MemberInfo: 'Int32[] Numbers'
         Array of 'System.Int32[]':
             Type: 'System.Int32'  Value: '53'
             Type: 'System.Int32'  Value: '57'
             Type: 'System.Int32'  Value: '59'

Attributes for member: 'Void TestMethod(System.Object)'
   [ExampleAttribute(Note = "This is a note on a method.")]
      Constructor: 'Void .ctor()'
      Constructor arguments:
      Named arguments:
         MemberInfo: 'System.String Note'
         Type: 'System.String'  Value: 'This is a note on a method.'

Attributes for parameter: 'System.Object arg'
   [ExampleAttribute()]
      Constructor: 'Void .ctor()'
      Constructor arguments:
      Named arguments:
*/

请参阅