从元数据说起
元数据的定义是“描述数据的数据”(data about data)。以数据库为例,存储到数据库表中的数据是按照一定的组织结构,和一定的关系约束等等存放的,描述这种组织结构的信息,例如表结构,表约束,字段约束等等,就可以成为元数据。
C# 源代码由CLI生成中间语言,保留了描述类型信息,接口,继承关系,类成员的元数据。我们可以通过反射来获取这些信息,并且除了获取之外,还可以通过反射在运行时动态调用一个类型的成员(而不仅仅在编译时)
-
- *
反射
System.Type
Type类是读取类型元数据信息的类,一个Type类的实例代表了目标类型的类型信息。
Type类表示类型声明,包括类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。
Type 类定义在System命名空间下。
以下是Type类中的部分信息
属性 | 说明 |
---|---|
Assembly | 获得程序集 |
Attributes | 获得与类型关联的特性 |
BaseType | 获得基类型 |
FullName | 获得包括命名空间的类型名 |
Name | 获得当前成员的名称 |
Namespace | 获取Type的命名空间 |
Is— | 用于判断当前类型 |
注:
关于"Is—",包括:
- 判断是否是类: IsClass;
- 判断是否是枚举:IsEnum;
- 判断是否是接口:IsInterface;
- 判断是否是抽象的:IsAbstract;
- 判断是否是数组:IsArray;
- 判断可见性:IsPublic,IsSealled,IsVisible
‘’’'等等
方法 | 说明 |
---|---|
Assembly | 获得程序集 |
Attributes | 获得与类型关联的特性 |
BaseType | 获得基类型 |
FullName | 获得包括命名空间的类型名 |
Name | 获得当前成员的名称 |
Namespace | 获取Type的命名空间 |
Is— | 用于判断当前类型 |
如下代码,反射某个类型并输出其类型名称
Type type = typeof(Type1);
//获取名字
Console.WriteLine(type.Name);
//获取全称:包括命名空间
Console.WriteLine(type.FullName);
更重要的是,通过这种方式可以动态引用类型成员,并进行赋值,读取,调用操作
//获取方法
Type1 typeinstance = new Type1();
foreach (var item in type.GetMethods())
{
Console.WriteLine("方法:" + item.Name);
}
//为typeinstance赋值:
type.GetProperty("StringProperty").SetValue(typeinstance, "hello
reflect");
Console.WriteLine("为typeinstance对象的属性StringProperty赋值:" +
typeinstance.StringProperty);
//调用方法
string
result=type.GetMethod("method").Invoke(typeinstance,null).ToString();
Console.WriteLine("调用方法method得到的结果为:" + result);
例如:获取数据库某个表的数据时,通常会在代码中定义一个与该表对应的Model类。将读取到的datatable中的值一一赋给这个类是一件非常痛苦的事情(尤其是字段特别多的情况下)。
事实上,通常Model类并不会具有很多复杂的方法,而是定义仅仅定义一些字段。因此可以尝试将Model的属性字段和数据库中表的字段名称定义的完全相同,应用反射的方法进行赋值操作:
public List<TESTTABLE> DateBaseHelper()
{
SqlConnection con = new SqlConnection("constr");
string sql = "select *from TESTTABLE";
SqlCommand cmd = new SqlCommand(sql,con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
List<TESTTABLE> tests = new List<TESTTABLE>();
Type type = typeof(TESTTABLE);
PropertyInfo[] properties = type.GetProperties();
for(int i=0;i<ds.Tables[0].Rows.Count;i++)
{
TESTTABLE test = new TESTTABLE();
foreach (var item in properties)
{
item.SetValue(test, ds.Tables[0].Rows[i][item.Name]);
}
tests.Add(test);
}
return tests;
}
注意:虽然这样做非常省代码,但是要考虑到反射也是有成本的(可能会影响性能,但是具体影响是否很大我没有做过深入了解)。这里主要用意还是想证明:反射是非常有用的。
typeof
typeof是一个运算符,对某一个类型名称或类型的实例使用相当于执行了GetType()方法。