欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

入门反射(一)

程序员文章站 2022-09-15 09:57:50
在很多项目的很多地方都发现了一个共同的术语 反射 有时候我在想这是个什么东西,能干啥。 这几天静下心来,好好地去翻了翻书,看了看别人的博客。 也自己比着写了两个泛型反射方法。还算理解了一小部分,写个记录。 上例子代码: 这是通过反射工厂来创建实例: 这是将Datatable里的数据反射到LIst集合 ......

在很多项目的很多地方都发现了一个共同的术语---反射

有时候我在想这是个什么东西,能干啥。

这几天静下心来,好好地去翻了翻书,看了看别人的博客。

也自己比着写了两个泛型反射方法。还算理解了一小部分,写个记录。

上例子代码:

这是通过反射工厂来创建实例:

public static T TFactory<T>() where T : class
{
     Type ty = typeof(T);
     string spaceStr = ty.Namespace; 
     string fullStr = ty.FullName;
     Assembly ass = Assembly.Load(spaceStr); 
     object ob = ass.CreateInstance(fullStr, true);

     return (T)ob; 
}  

这是将Datatable里的数据反射到LIst集合中:

public static List<T> ToList<T>(this DataTable dt)
{
    if (dt == null || dt.Rows.Count == 0)
    {
        return default(List<T>);
    }

    List<T> list = new List<T>();
    Type type = typeof(T);   
    PropertyInfo[] per = type.GetProperties(); 

    foreach (DataRow row in dt.Rows) 
    {
        T entity = Activator.CreateInstance<T>();
        foreach (PropertyInfo p in per)
        {
           object obj = Convert.ChangeType(row[p.Name], p.PropertyType); 
           p.SetValue(entity, obj);
        }
        list.Add(entity);
    }

    return list;
}

猛地一看是不是有点哇塞~,很酷的感觉。

来看看这个反射是个什么东西吧,按照我的理解+书上的指引来大体粗略的写一下反射

反射

大多数程序都要处理数据,包括读,写,操作和显式数据。

然而,对于某些程序来说,他们操作的不是数字,文本或图形,而是程序和程序类型本身的信息。

有关程序及其类型的数据被称为元数据(matadata),他们保存在程序的程序集中(.dll)。

程序在运行时,可以查看其它程序集或其本身的元数据。一个运行的程序查看本身的元数据或其它程序的元数据的行为叫做"反射"。

反射命名空间:System.Reflection

Type类

BCL(基类库)声明了一个叫做Type的抽象类,他被设计用来包含类型的特性。使用这个类能让我们获取程序使用的类型的信息。

由于Type是抽象类,因此他不能有实例。而是在运行时,CLR(公共语言运行库)从Type(RunTimeType)派生的类的实例,Type包含了类型的信息。

当我们要访问这些实例时,CLR不会返回派生类的引用而是Type基类的引用,

需要了解的Type重要事项:

1.对于程序中用到的每一个类型,CLR都会创建一个包含这个类型的Type类型的对象。

2.程序中用到的每一个类型都会关联到独立的Type类的对象。

3.不管创建的类有多少个实例,只有一个Type对象会关联到所有的这些实例。

如图:一个运行的程序,他有两个MyClass对象和一个OtherClass对象。注意:尽管有两个MyClass的实例,只会有一个Type对象来表示他。

入门反射(一)

我们可以从Type对象中获取需要了解的有关类型的几乎所有信息。

列一下常用的成员吧。

System.Type类部分的成员。

入门反射(一)

 

获取Type对象

object类包含了一个叫做GetType的方法,他返回对实例的Type对象的引用。

由于每一个类型最终都是从object继承的,所以我么可以在任何类型对象上使用GetType方法来获取他的Type对象。

Student stu = new Student();
Type type = stu.GetType();//stu可以时任何一个对象实例化后

下面演示一下一个基类跟派生子类。在foreach循环中输出类的名字以及公用字段的名字。

基类与派生类:

class BaseClass //基类
{
    public int BaseField = 0;
}

class DerivedClass : BaseClass //派生类
{
    public int DerivedField = 0;
}

通过反射输出类信息:

BaseClass bc = new BaseClass();    //基类
DerivedClass dc = new DerivedClass();//派生类

BaseClass[] bca = new BaseClass[] { bc, dc };

foreach (var v in bca)
{
    Type type = v.GetType();
    Console.WriteLine("Type:{0}",type.Name);//输出类名称

    FieldInfo[] fields = type.GetFields();//获取所有公用字段
    foreach (var f in fields)
         Console.WriteLine("Field:{0}",f.Name);//输出公用字段名称
}

输出结果为:

入门反射(一)

类名与公用属性全部被输出了。

我们还可以通过typeof运算符来获取Type对象。

只需提供类型名作为操作数,他就会返回Type对象的引用(通常都会用在泛型方法中),如代码所示。

Type type = typeof(BaseClass);

总结

反射我只是初窥门径,如果有错误的地方请各位大佬指正。

反射肯定不会只输出这些名字。

反射还可以设置类型里公用的值。还可以调用类型中公用的方法。

等到下一篇讲吧。