入门反射(一)

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

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

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

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

上例子代码:

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

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

总结

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

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

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

等到下一篇讲吧。

posted @ 2018-06-04 15:44 捕头的爱 阅读(...) 评论(...) 编辑 收藏