博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#反射了解(转)
阅读量:6237 次
发布时间:2019-06-22

本文共 3954 字,大约阅读时间需要 13 分钟。

Reflection,中文翻译为反射。这是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息,例如:Assembly类可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。Type类可以获得对象的类型信息,此信息包含对象的所有要素:方法、构造器、属性等等,通过Type类可以得到这些要素的信息,并且调用之。MethodInfo包含方法的信息,通过这个类可以得到方法的名称、参数、返回值等,并且可以调用之。诸如此类,还有FieldInfo、EventInfo等等,这些类都包含在System.Reflection命名空间下。

一、Type类于获取类型信息
System.Type 类对于反射起着核心的作用。当反射请求加载的类型时,公共语言运行库将为它创建一个 Type。您可以使用 Type 对象的方法、字段、属性和嵌套类来查找有关该类型的所有信息。
大家运行一下下面的代码根据结果分析一下就能比较清楚的理解Type了

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
MyClass m
= new MyClass();
Type type
= m.GetType();
Console.WriteLine(
"类型名:" + type.Name);
Console.WriteLine(
"类全名:"+type.FullName);
Console.WriteLine(
"命名空间名:"+type.Namespace);
Console.WriteLine(
"程序集名:"+type.Assembly);
Console.WriteLine(
"模块名:"+type.Module);
Console.WriteLine(
"基类名:"+type.BaseType);
Console.WriteLine(
"是否类:"+type.IsClass);
Console.WriteLine(
"类的公共成员:");
MemberInfo[] memberInfos
= type.GetMembers();//得到所有公共成员
foreach (var item in memberInfos)
{
Console.WriteLine(
"{0}:{1}",item.MemberType,item);
}
}
}
class MyClass
{
public string m;
public void test()
{ }
public int MyProperty { get; set; }
}
}

二、获取程序集元数据

Assembly类定义了一个程序集,它是一个可重用、无版本冲突并且可自我描述的公共语言运行库应用程序构造块。因为程序集中是使用元数据进行自我描述的,所以我们就能通过其元数据得到程序集内部的构成。结合Assembly和反射能够获取程序集的元数据,但是首先要将程序集装入内存中。可以使用Assembly类的多种静态Load方法加载程序集。
下面的程序显示程序集的信息

public static void Main()
{
//获取当前执行代码的程序集
Assembly assem = Assembly.GetExecutingAssembly();
Console.WriteLine(
"程序集全名:"+assem.FullName);
Console.WriteLine(
"程序集的版本:"+assem.GetName().Version);
Console.WriteLine(
"程序集初始位置:"+assem.CodeBase);
Console.WriteLine(
"程序集位置:"+assem.Location);
Console.WriteLine(
"程序集入口:"+assem.EntryPoint);
Type[] types
= assem.GetTypes();
Console.WriteLine(
"程序集下包含的类型:");
foreach (var item in types)
{
Console.WriteLine(
"类:"+item.Name);
}
}

三、动态加载类型

早绑定是在编译时绑定对象类型,而晚绑定是在运行时才绑定对象的类型。利用反射可以实现晚绑定,即动态加载类型,并调用他们的方法,下边是MSDN中的一个例子,详细的解释信息见注释

namespace ConsoleApplication2
{
public class Example
{
private int factor;
public Example(int f)
{
factor
= f;
}
public int SampleMethod(int x)
{
Console.WriteLine(
"\nExample.SampleMethod({0}) executes.", x);
return x * factor;
}
public static void Main()
{
//获取当前执行代码的程序集
Assembly assem = Assembly.GetExecutingAssembly();
Console.WriteLine(
"Assembly Full Name:");
Console.WriteLine(assem.FullName);
// The AssemblyName type can be used to parse the full name.
AssemblyName assemName = assem.GetName();
Console.WriteLine(
"\nName: {0}", assemName.Name);
Console.WriteLine(
"Version: {0}.{1}",
assemName.Version.Major, assemName.Version.Minor);
Console.WriteLine(
"\nAssembly CodeBase:");
Console.WriteLine(assem.CodeBase);
// 从程序集众创建一个Example实例并且用object类型的引用o指向它,同时调用一个输入参数的构造函数
Object o = assem.CreateInstance("ConsoleApplication2.Example", false,
BindingFlags.ExactBinding,
null, new Object[] { 2 }, null, null);
//构造Example类的一个晚绑定的方法SampleMethod
MethodInfo m = assem.GetType("ConsoleApplication2.Example").GetMethod("SampleMethod");
//调用刚才实例化好的Example对象o中的SampleMethod方法,传入的参数为42
Object ret = m.Invoke(o, new Object[] { 42 });
Console.WriteLine(
"SampleMethod returned {0}.", ret);
Console.WriteLine(
"\nAssembly entry point:");
Console.WriteLine(assem.EntryPoint);
}
}

2.

3.

要用C#反射技术的话,首先得引入System.Reflection 命名空间,这个命名空间里的类,具有动态加载程序集、类型,动态调用方法、设置和取得属性和字段的值、可以获取类型和方法的信息的功能。

要想对一个类型实例的属性或字段进行动态赋值或取值,首先得得到这个实例或类型的Type,微软已经为我们提供了足够多的方法。

1
Class MyClass
2
{
3
private
int
field;
4
public
int
Field
5
{
6
get
7
{
8
return
this
.field;
9
}
10
set
11
{
12
this
.field
=
value;
13
}
14
}
15
}

如果有个这个类型的实例:

MyClass myObj = new MyClass();
我们要动态的为这个实例的属性
Field赋值,那么得先得到这个实例的类型:

Type t
=
typeof
(MyClass);

另一种方法是:

Type t
=
myObj.GetType();

只要我们得到了对象的类型那么我们就可以利用反射对这个对象“为所欲为”了,哈哈。

t.GetProperty(
"
Field
"
).SetValue(myObj,
1
,
null
);

这样我们就为对象里的属性Field赋值了。如果把属性名和要赋的值写道配置文件里的话,我们就可以达到程序运行期间动态的为属性赋值了。

利用反射获取属性值的方法:

int
propValue
=
Convert.ToInt32(t.GetProperty(
"
Field
"
).GetValue(myObj,
null
));
你可能感兴趣的文章
从零开始学MVC3——创建项目
查看>>
java笔记:熟练掌握线程技术---基础篇之解决资源共享的问题(中)--中篇
查看>>
Windows MDL原理总结
查看>>
12篇学通C#网络编程——第二篇 HTTP应用编程(上)(转)
查看>>
SSH服务连接时常见问题解答
查看>>
SQL Server2012中的Throw语句尝试
查看>>
[观点]尽可能的缓存
查看>>
怎么了解某一研究领域的总体发展趋势
查看>>
关于MapControl和PageLayoutControl同步的一点分析
查看>>
Convert an object into Json using SBJson or other JSON library
查看>>
C++中的类所占内存空间总结
查看>>
Java之命令模式(Command Pattern)
查看>>
WCF RIA Services 简单应用
查看>>
毕业了,校园里走走看看——华中科技大学
查看>>
C#.NET 添加图片水印
查看>>
wcf系列5天速成——第一天 binding的使用(1)
查看>>
ExtJs布局之viewport
查看>>
Lua学习笔记
查看>>
1、第一个JSP
查看>>
希尔排序(Shell)
查看>>