反射、元数据、动态编程

反射

1、定义

MicroSoft Docs 给出的定义:

反射提供描述程序集、模块和类型的对象(Type 类型)。 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型,然后调用其方法或访问器字段和属性。img

                                                                                       [图片来自 《C# 7.0 本质论》]

元数据:C# 编写的程序编译成一个程序集,程序集会包含元数据、编译代码和资源。 元数据包含内容:

  • 程序或类库中每一个类型的描述;

  • 清单信息,包括与程序本身有关的数据,以及它依赖的库;

  • 在代码中嵌入的自定义特性,提供与特性所修饰的构造有关的额外信息。

反射:在运行时检查并使用元数据和编译代码的操作称为反射。

一个程序集包含的内容:

img

[图片来自 《C# 7.0 核心技术指南》]

2、用途

反射在以下情况下很有用:

  • 需要访问程序元数据中的特性时。

  • 检查和实例化程序集中的类型。

  • 在运行时构建新类型。使用System.Reflection.Emit中的类。

  • 执行后期绑定,访问在运行时创建的在类型上的方法。

3、Type信息:

System.Type 类是反射的中心。

当反射提出请求时,公共语言运行时为已加载的类型创建 Type 。 可使用 Type 对象的方法、字段、属性和嵌套类来查找该类型的任何信息。

获取type:

int i = 12;
Console.WriteLine(i.GetType());
Console.WriteLine(typeof(int));

typeof()静态方法,从类型获取type;

GetType()从实例化对象获取type;

结合程序集来使用:

//结合程序集来使用
Assembly val = Assembly.LoadFrom(@"E:\Demo\IsInAsTest\bin\Debug\netcoreapp3.1\IsInAsTest.dll"); 
Console.WriteLine(val);
//完全限定程序集中类型"IsInAsTest.Circle"
Type type = val.GetType("IsInAsTest.Circle");
Console.WriteLine($"type:{type}");
Type[] types = val.GetTypes();
Console.WriteLine(types);
//循环打印程序集中的类型
foreach (var item in types)
{
   Console.WriteLine(item);
}

运行结果如下:

列出类的构造函数ConstructorInfo,使用 MemberInfo、MethodInfo、FieldInfo 或 PropertyInfo 对象获取类型的方法、属性、事件和字段的相关信息。不再赘述。

4、反射在泛型上的使用

直接拿官网demo对比

Type d1 = typeof(Dictionary<,>);
 Dictionary<string, Example> d2 = new Dictionary<string, Example>();
​
 Example.DisplayGenericType(d1);
 Example.DisplayGenericType(d2.GetType());
 Type[] typeArgus = { typeof(string), typeof(Example) };
 Type constructed = d1.MakeGenericType(typeArgus);
 Example.DisplayGenericType(constructed);
 object o = Activator.CreateInstance(constructed);
 Console.WriteLine("\r\nCompare types obtained by different methods:");
 Console.WriteLine("   Are the constructed types equal? {0}",
     (d2.GetType() == constructed));
 Console.WriteLine("   Are the generic definitions equal? {0}",
     (d1 == constructed.GetGenericTypeDefinition()));
 Example.DisplayGenericType(typeof(Test<>));
 public class Example
    {
        // The following method displays information about a generic
        // type.
        public static void DisplayGenericType(Type t)
        {
            Console.WriteLine("\r\n {0}", t);
            Console.WriteLine("   Is this a generic type? {0}",
                t.IsGenericType);
            Console.WriteLine("   Is this a generic type definition? {0}",
                t.IsGenericTypeDefinition);
​
            // Get the generic type parameters or type arguments.
            Type[] typeParameters = t.GetGenericArguments();
​
            Console.WriteLine("   List {0} type arguments:",
                typeParameters.Length);
            foreach (Type tParam in typeParameters)
            {
                if (tParam.IsGenericParameter)
                {
                    DisplayGenericParameter(tParam);
                }
                else
                {
                    Console.WriteLine("      Type argument: {0}",
                        tParam);
                }
            }
        }
        // The following method displays information about a generic
        // type parameter. Generic type parameters are represented by
        // instances of System.Type, just like ordinary types.
        public static void DisplayGenericParameter(Type tp)
        {
            Console.WriteLine("      Type parameter: {0} position {1}",
                tp.Name, tp.GenericParameterPosition);
​
            Type classConstraint = null;
​
            foreach (Type iConstraint in tp.GetGenericParameterConstraints())
            {
                if (iConstraint.IsInterface)
                {
                    Console.WriteLine("         Interface constraint: {0}",
                        iConstraint);
                }
            }
​
            if (classConstraint != null)
            {
                Console.WriteLine("         Base type constraint: {0}",
                    tp.BaseType);
            }
            else
            {
                Console.WriteLine("         Base type constraint: None");
            }
​
            GenericParameterAttributes sConstraints =
                tp.GenericParameterAttributes &
                GenericParameterAttributes.SpecialConstraintMask;
​
            if (sConstraints == GenericParameterAttributes.None)
            {
                Console.WriteLine("         No special constraints.");
            }
            else
            {
                if (GenericParameterAttributes.None != (sConstraints &
                    GenericParameterAttributes.DefaultConstructorConstraint))
                {
                    Console.WriteLine("         Must have a parameterless constructor.");
                }
                if (GenericParameterAttributes.None != (sConstraints &
                    GenericParameterAttributes.ReferenceTypeConstraint))
                {
                    Console.WriteLine("         Must be a reference type.");
                }
                if (GenericParameterAttributes.None != (sConstraints &
                    GenericParameterAttributes.NotNullableValueTypeConstraint))
                {
                    Console.WriteLine("         Must be a non-nullable value type.");
                }
            }
        }
    }
打印信息如下:
System.Collections.Generic.Dictionary`2[TKey,TValue]
   Is this a generic type? True
   Is this a generic type definition? True
   List 2 type arguments:
      Type parameter: TKey position 0
         Base type constraint: None
         No special constraints.
      Type parameter: TValue position 1
         Base type constraint: None
         No special constraints.
​
 System.Collections.Generic.Dictionary`2[System.String,ReflectionTest.Example]
   Is this a generic type? True
   Is this a generic type definition? False
   List 2 type arguments:
      Type argument: System.String
      Type argument: ReflectionTest.Example
​
 System.Collections.Generic.Dictionary`2[System.String,ReflectionTest.Example]
   Is this a generic type? True
   Is this a generic type definition? False
   List 2 type arguments:
      Type argument: System.String
      Type argument: ReflectionTest.Example
​
Compare types obtained by different methods:
   Are the constructed types equal? True
   Are the generic definitions equal? True
​
 ReflectionTest.Test`1[T]
   Is this a generic type? True
   Is this a generic type definition? True
   List 1 type arguments:
      Type parameter: T position 0
         Interface constraint: ReflectionTest.ITestArgument
         Base type constraint: None
         Must have a parameterless constructor.

 

 参考资料:

痴者工良博客:https://www.cnblogs.com/whuanle/p/12115505.html

posted @ 2020-10-16 08:23  牧火逐云  阅读(97)  评论(0)    收藏  举报