C#中使用类型元数据
最近一直在系统的学习.NetFramework2.0,昨晚上刚完成了类型元数据的Task,贴出来给大家看看。
l 场景
你是 Adventure Works 公司的开发人员,当前你需要创建一个应用程序,以报告由该公司开发人员编写的代码。该应用程序将加载一个程序集并使用反射来生成要用于代码评审和文档化的报告。要改进性能,需要将该应用程序创建为控制台应用程序。在本练习中,将使用 Assembly 类加载程序集,而程序集名称和路径应由用户提供。
你希望创建一个对不同应用程序中编写的代码进行文档化的应用程序。在本练习中,该应用程序将使用多个信息类型反射类,以生成一个用于代码评审和文档化的基于控制台的报告。该报告会列举程序集的名称、位置、版本和其他程序集级别元数据。该报告还会列举程序集中的模块、类、成员、方法和属性。
步骤1:显示程序集信息
1) 声明一个接受程序集作为参数的名为GenerateReport 的方法。
2) 编写代码,以显示程序集信息。
根据程序集在全局程序集缓存中的位置,显示程序集的名称和位置以及程序集的状态。
结果:已经显示程序集信息。
步骤2:显示程序集中所有模块和类型
1) 使用 GetModules 方法创建一个包含程序集中模块的报告。
该代码会为程序集中的每个模块调用DisplayModuleInfo方法。
2) 声明一个接受Module 方法作为参数的名为 DisplayModuleInfo 的方法。
3) 通过使用 GetTypes 方法来显示每个方法中包含的类型列表。
该代码会为模块中的每个类型调用 DisplayTypeInfo 方法。
结果:已经显示了该程序集包含的模块列表和每个模块包含的类型列表。
步骤3:显示所有类型中的字段、属性和方法。
1) 声明一个接受Type 作为参数的名为 DisplayTypeInfo 的方法。
2) 使用 GetFields 方法显示所有类型中的字段列表。
该列表应包含以下信息:
l 字段名
l 字段类型
l 字段是公共还是私有
3) 使用 GetProperties 方法显示所有属性列表。
该列表应包含以下信息:
l 属性名
l 属性类型
l 属性是可读还是可写
4) 显示当前类型中所有方法的列表。
该代码会为类型中的每个方法调用 DisplayMethodInfo 方法。
结果:已经显示每种类型中的字段列表、属性列表以及方法列表。
步骤4:显示所有方法中包含的信息
1) 声明一个接受 MethodInfo 作为参数的名为 DisplayMethodInfo 的方法。
2) 使用 GetParameters 方法显示方法头文件信息。
3) 使用 GetParameters 方法显示所有参数的列表。
该列表应包含以下信息:
l 参数名
l 参数类型
l 参数是否为 IsOptional、IsOut 或 IsRetval。
4) 使用 GetMethodBody 方法显示关于每个方法的信息。
该信息应该包含方法中定义的堆栈大小和局部变量详细信息,例如LocalIndex和LocalType。
5) 编译并运行该应用程序。
主要代码如下:
2using System.Collections.Generic;
3using System.Text;
4using System.Reflection;
5
6namespace crse3366ae_lab01
7{
8 class Program
9 {
10 static string ReadAssemblyFullPath()
11 {
12 string AssemblyPath, AssemblyName;
13 Console.Write("Type the assembly path: ");
14 AssemblyPath = Console.ReadLine();
15 Console.Write("Type the assembly name: ");
16 AssemblyName = Console.ReadLine();
17 return AssemblyPath + @"\" + AssemblyName;
18 }
19
20 static void Main(string[] args)
21 {
22 string AssemblyFullPath;
23 AssemblyFullPath = ReadAssemblyFullPath();
24 GenerateReport(AssemblyFullPath);
25 Console.Read();
26 }
27 static void GenerateReport(string path)
28 {
29 Assembly myAssemble = Assembly.LoadFile(path);
30 Console.WriteLine(myAssemble.FullName);
31 //myAssemble.
32 Console.WriteLine(string.Empty.PadLeft(45, '-'));
33 foreach (Type type in myAssemble.GetTypes())
34 {
35 Console.WriteLine("The name of Assemble is:"+type.Name);
36 Console.WriteLine("The path is:" + type.FullName);
37 }
38 GetModules(myAssemble);
39 }
40 static void GetModules(Assembly name)
41 {
42 Console.WriteLine(string.Empty.PadLeft(40, '-'));
43 foreach (Module module in name.GetModules())
44 {
45 Console.WriteLine("Module name:" + module.Name);
46 DisplayModuleInfo(module);
47 }
48 }
49 static void DisplayModuleInfo(Module module)
50 {
51 Console.WriteLine(string.Empty.PadLeft(35, '-'));
52 foreach (Type type in module.GetTypes())
53 {
54 Console.WriteLine("Module type name is:" + type.Name);
55 DisplayTypeInfo(type);
56 }
57 }
58 static void DisplayTypeInfo(Type type)
59 {
60 foreach (FieldInfo fieldInfo in type.GetFields())
61 {
62 Console.WriteLine("The name of this field is:" + fieldInfo.Name);
63 Console.WriteLine("The type of this field is:" + fieldInfo.GetType().ToString());
64 if (fieldInfo.IsPrivate)
65 {
66 Console.WriteLine("This field is Private!");
67 }
68 else
69 {
70 Console.WriteLine("This field is public");
71 }
72 }
73 Console.WriteLine(string.Empty.PadLeft(30, '-'));
74 foreach (PropertyInfo propertyInfo in type.GetProperties())
75 {
76 Console.WriteLine("The name of this property is:" + propertyInfo.Name);
77 Console.WriteLine("Type of this property is:" + propertyInfo.PropertyType.ToString());
78 if (propertyInfo.CanWrite)
79 {
80 Console.WriteLine("This property can write!");
81 }
82 else
83 {
84 Console.WriteLine("This property can't be write");
85 }
86 }
87 Console.WriteLine(string.Empty.PadLeft(30, '-'));
88 foreach (MethodInfo method in type.GetMethods())
89 {
90 Console.WriteLine("Method name:" + method.Name);
91 DisplayMethodInfo(method);
92 }
93 }
94 static void DisplayMethodInfo(MethodInfo method)
95 {
96 Console.WriteLine(string.Empty.PadLeft(25, '-'));
97 foreach (ParameterInfo parInfo in method.GetParameters())
98 {
99 Console.WriteLine("Parameter name is:"+parInfo.Name);
100 Console.WriteLine("Parameter type is:" + parInfo.ParameterType.ToString());
101 if (parInfo.IsOptional)
102 {
103 Console.WriteLine("This parameter is option!");
104 }
105 else
106 Console.WriteLine("This parrameter is not option!");
107 if (parInfo.IsOut)
108 {
109 Console.WriteLine("This parameter is out!");
110 }
111 else
112 Console.WriteLine("This parameter is not out!");
113 if (parInfo.IsRetval)
114 Console.WriteLine("and is retval");
115 else
116 Console.WriteLine("and is not retval");
117 }
118 if (method.GetMethodBody() != null)
119 {
120 GetMethodBody(method.GetMethodBody());
121 }
122 }
123 static void GetMethodBody(MethodBody body)
124 {
125 Console.WriteLine(string.Empty.PadLeft(20, '-'));
126 Console.WriteLine("Body Information :");
127 Console.WriteLine("Max stack size:" + body.MaxStackSize);
128 Console.WriteLine("Local variables are initialized:" + body.InitLocals);
129 Console.WriteLine(string.Empty.PadLeft(15, '-'));
130 foreach (LocalVariableInfo local in body.LocalVariables)
131 {
132 Console.WriteLine("Index of local var is:" + local.LocalIndex);
133 Console.WriteLine("Type of local var is:"+local.LocalType.ToString());
134 }
135 Console.WriteLine(string.Empty.PadLeft(20, '*'));
136 }
137 }
138}
139
龟看上去很慢很慢,而且还有些憨,虽然没有兔子跑的快,但是只要有坚持不懈的毅力,就一定会到达成功的比彼岸.如果自己是龟,就不要试图把自己变成兔子,我就是那只憨龟。