本文整理所得:
一、杂谈(比较详细)
文章出处:http://www.cnblogs.com/axzhz/archive/2006/11/01/546493.html
【开篇】
这篇帖子真的憋了好久.无处下笔啊!
搜了搜园子,已经有棵这方面的好白菜了!链接如下
http://www.cnblogs.com/whxleem/category/4641.html
以此为资料,学习了一下,但心有不甘,要不前两篇许下的承诺就没法实现了!于是有了这篇帖子.
【正文】
①什么是反射?
反射提供了封装程序集、模块和类型的对象。
您可以使用反射动态地创建类型的实例(见④ ),将类型绑定到现有对象(这个不会),或从现有对象中获取类型(见②③ )。然后,可以调用类型的方法或访问其字段和属性。
最最简单的反射:如下
1
using System;
2
using System.Reflection;
3
namespace TestReflection
4 {
5
class Program
6 {
7
static void Main(string[] args)
8 {
9
//创建两个对象【object和Objetct好像没有区别啊??连提示都一样!】
10
object A = new AX();
11
Object B = new AXzhz();
12
//获取对象的类型
13
new TestObjectType().TestObjectTypeNow(A, B);
14
}
15
}
16![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
class AX
18
{
19
}
20![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
class AXzhz
22![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
23
}
24![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
25
class TestObjectType
26![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
27
//构造函数的默认修饰为private
28
internal void TestObjectTypeNow(object A, object B)
29![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
30
Type tpA = A.GetType();
31
Type tpB = B.GetType();
32
Console.WriteLine(tpA.FullName);
33
Console.WriteLine(tpB.FullName);
34
Console.ReadLine();
35
}
36
}
37
}
输出结果:
TestReflection.AX
TestReflection.AXzhz
【分析】通过对象实例(A,B),可以使用GetType()方法获取该对象属于哪个类.非类型转化后的类,而是构造该类型的类
【应用】给个变量/对象实例,测试下它属于哪个类,顺带还给出该类所属的Assembly
【附】另外一种获取类型的方法是通过Type.GetType以及Assembly.GetType方法,如:
Type t = Type.GetType("TestReflection.AX");
需要注意的是,前面我们讲到了命名空间和装配件的关系,要查找一个类,必须指定它所在的装配件
Type类:表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。 发晕,对泛型没研究.
②我们获得的Type实例有什么用?
ⅰ获得类名:如上面例子的FullName属性,返回TestReflection.AX
这个也比较恶心,直接用A.ToString();返回的也是这个结果.
ⅱ创建该类的对象.你首先通过ⅰ来获得类名AX
AX ax = (AX)Activator.CreateInstance(tpA);
都知道是AX类型了,怎么不new一个???鸡肋的东西.
上面的【附】真不知道是干嘛吃的,都知道了类TestReflection.AX,直接new一个就可以了.
ⅲ获得对象所属类的相关信息
通过tpA的相关属性,来得到该类的相关信息.
其实你通过A的相关属性,也可以得到该类的相关信息.还简单省事,真不知道Type类到底是干嘛吃的.
③窥一斑而知全豹,一个对象实例泄漏的密秘(这个比较爽)
通过一个对象实例,我们可以获得包含这个对象实例的类的Assembly,进而获得整个Assembly的信息.
1
using System;
2
using System.Reflection;
3
namespace TestReflection
4![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
5
class Program
6![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
7
public static void Main(string[] args)
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
9
object A = new AX();
10
//获取对象所属的Assembly的所有类的基本信息
11
new TestObjectType().TestObjectTypeNow(A);
12
}
13
}
14![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
class AX
16![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
17
internal int kkkkkkkk = 0;
18
public int ooooooooo;
19
private int property;
20![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
public int Property
22![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
23![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get { return property; }
24![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set { property = value; }
25
}
26
public void A()
27![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
28
Console.WriteLine("AX's function!~");
29
}
30
}
31![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
32
class AXzhz
33![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
34
}
35![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
36
class TestObjectType
37![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
38
//构造函数的默认修饰为private
39
internal void TestObjectTypeNow(object A)
40![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
41
Type tpA = A.GetType();
42
Assembly assembly = tpA.Assembly;
43
Type[] types = assembly.GetTypes();
44
foreach (Type type in types)
45![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
46
Console.WriteLine("【类名】"+type.FullName);
47
//获取类型的结构信息
48
ConstructorInfo[] myconstructors = type.GetConstructors();
49
Show(myconstructors);
50
//获取类型的字段信息
51
FieldInfo[] myfields = type.GetFields();
52
Show(myfields);
53
//获取方法信息
54
MethodInfo[] myMethodInfo = type.GetMethods();
55
Show(myMethodInfo);
56
//获取属性信息
57
PropertyInfo[] myproperties = type.GetProperties();
58
Show(myproperties);
59
//获取事件信息,这个项目没有事件,所以注释掉了,
60
//通过这种办法,还可以获得更多的type相关信息.
61
//EventInfo[] Myevents = type.GetEvents();
62
//Show(Myevents);
63
}
64
Console.ReadLine();
65
}
66
//显示数组的基本信息
67
public void Show(object[] os)
68![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
69
foreach (object var in os)
70![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
71
Console.WriteLine(var.ToString());
72
}
73
Console.WriteLine("----------------------------------");
74
}
75
}
76
}
【注】通过测试,发现只能获得public类型的信息.
④动态创建对象实例【经典】
是实现抽象工厂的基础,也是实现抽象工厂的核心技术,通过它,可以动态创建一个你想要的对象.如下面的例子是演示如何动态创建ChineseName或EnglishName的实例
在软件开发尤其是框架和底层开发时,为了更灵活的控制代码,常常需要进行一些动态的操作。比如根据用户的输入等动态的调用类中的方法或者根据数据库表结构、用户要求动态的生成一些类,然后再动态的调用类中的方法。当然使用这些方式时会对性能有一点影响,具体使用过程中可以根据实际情况来定,不过一般的B/S开发中主要的瓶颈还是在数据库操作和网速方面,这点影响应该可以忽略的
![](https://www.cnblogs.com/Emoticons/msn/regular_smile.gif)
下面我就从这两个方面来说说动态代码的使用:
一、反射的使用可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
需要使用的命名空间:
System.Reflection反射的作用很多,下面的例子主要是看一下怎么动态的调用类中的方法。
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ContractedBlock.gif)
例子类
class ReflTest1
{
private string _prop1;
![](http://www.cnblogs.cc2/Images/OutliningIndicators/InBlock.gif)
public string Prop1
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _prop1; }
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _prop1 = value; }
}
public void Write1(string strText)
{
Console.WriteLine("111111111:" + strText);
}
public void Write2(string strText)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine("222222222:" + strText);
}
public void MyWrite(string strText)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine("3333333333:" + strText);
}
}
![](http://www.cnblogs.cc2/Images/OutliningIndicators/None.gif)
这个例子中提供了三个方法和一个属性,下面的代码来动态的调用它们:
string strText = "abcd";
![](http://www.cnblogs.cc2/Images/OutliningIndicators/None.gif)
BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
![](http://www.cnblogs.cc2/Images/OutliningIndicators/None.gif)
Type t = typeof(ReflTest1);
MethodInfo[] mi = t.GetMethods(flags);
Object obj = Activator.CreateInstance(t);
![](http://www.cnblogs.cc2/Images/OutliningIndicators/None.gif)
foreach (MethodInfo m in mi)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
if (m.Name.StartsWith("Write"))
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
m.Invoke(obj, new object[]
{ strText });
}
}
![](http://www.cnblogs.cc2/Images/OutliningIndicators/None.gif)
MethodInfo mMy = t.GetMethod("MyWrite");
if (mMy != null)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
mMy.Invoke(obj, new object[]
{ strText });
}
![](http://www.cnblogs.cc2/Images/OutliningIndicators/None.gif)
BindingFlags用来设置要取得哪些类型的方法,然后我们就可以取得这些方法来动态的调用。(当然为了可以循环的调用方法,在方法的命名方面可以自己指定一个规则)
二、动态生成类我们可以在程序运行过程中调用.NET中提供的编译类,动态的将一段string编译成一个类,然后再通过反射来调用它
需要使用的命名空间:
System.CodeDom System.CodeDom.Compiler Microsoft.CSharp System.Reflection动态创建、编译类的代码如下:
public static Assembly NewAssembly()
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
//创建编译器实例。
provider = new CSharpCodeProvider();
//设置编译参数。
paras = new CompilerParameters();
paras.GenerateExecutable = false;
paras.GenerateInMemory = true;
![](http://www.cnblogs.cc2/Images/OutliningIndicators/InBlock.gif)
//创建动态代码。
StringBuilder classSource = new StringBuilder();
classSource.Append("public class DynamicClass \n");
classSource.Append("{\n");
![](http://www.cnblogs.cc2/Images/OutliningIndicators/InBlock.gif)
//创建属性。
classSource.Append(propertyString("aaa"));
classSource.Append(propertyString("bbb"));
classSource.Append(propertyString("ccc"));
![](http://www.cnblogs.cc2/Images/OutliningIndicators/InBlock.gif)
classSource.Append("}");
![](http://www.cnblogs.cc2/Images/OutliningIndicators/InBlock.gif)
System.Diagnostics.Debug.WriteLine(classSource.ToString());
![](http://www.cnblogs.cc2/Images/OutliningIndicators/InBlock.gif)
//编译代码。
CompilerResults result = provider.CompileAssemblyFromSource(paras, classSource.ToString());
![](http://www.cnblogs.cc2/Images/OutliningIndicators/InBlock.gif)
//获取编译后的程序集。
Assembly assembly = result.CompiledAssembly;
![](http://www.cnblogs.cc2/Images/OutliningIndicators/InBlock.gif)
return assembly;
}
![](http://www.cnblogs.cc2/Images/OutliningIndicators/None.gif)
private static string propertyString(string propertyName)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
StringBuilder sbProperty = new StringBuilder();
sbProperty.Append(" private int _" + propertyName + " = 0;\n");
sbProperty.Append(" public int " + "" + propertyName + "\n");
sbProperty.Append(" {\n");
sbProperty.Append(" get{ return _" + propertyName + ";} \n");
sbProperty.Append(" set{ _" + propertyName + " = value; }\n");
sbProperty.Append(" }");
return sbProperty.ToString();
}
propertyString方法就是用来拼写字符串的
整个代码比较简单,主要步骤就是:1、拼写类的字符串 2、调用CSharpCodeProvider类进行编译得到程序集(assembly)
接下来就可以利用之前反射的方法来动态调用这个类中的属性了:
Assembly assembly = NewAssembly();
![](http://www.cnblogs.cc2/Images/OutliningIndicators/None.gif)
object Class1 = assembly.CreateInstance("DynamicClass");
ReflectionSetProperty(Class1, "aaa", 10);
ReflectionGetProperty(Class1, "aaa");
![](http://www.cnblogs.cc2/Images/OutliningIndicators/None.gif)
object Class2 = assembly.CreateInstance("DynamicClass");
ReflectionSetProperty(Class1, "bbb", 20);
ReflectionGetProperty(Class1, "bbb");
DynamicClass是我动态类的类名,aaa和bbb是其中的属性
ReflectionSetProperty和ReflectionGetProperty代码如下:
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ContractedBlock.gif)
给属性赋值
private static void ReflectionSetProperty(object objClass, string propertyName, int value)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
PropertyInfo[] infos = objClass.GetType().GetProperties();
foreach (PropertyInfo info in infos)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (info.Name == propertyName && info.CanWrite)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
info.SetValue(objClass, value, null);
}
}
}
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ContractedBlock.gif)
取得属性的值
private static void ReflectionGetProperty(object objClass, string propertyName)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
PropertyInfo[] infos = objClass.GetType().GetProperties();
foreach (PropertyInfo info in infos)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (info.Name == propertyName && info.CanRead)
![](http://www.cnblogs.cc2/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
System.Console.WriteLine(info.GetValue(objClass, null));
}
}
}
三、根据类型获取对象并调用方法
http://www.cnblogs.com/fineboy/archive/2005/09/02/228684.html
http://www.cnblogs.com/jax/archive/2009/10/16/1584527.html