反射
一个运行的程序查看本身的元数据或者其他程序集的元数据的行为叫做反射。
元数据,就是描述数据的数据。Metadata存在于任何对数据和数据关系的描述中,
NET是基于面向对象的,所以元数据描述的主要目标就是面向对象的基本元素:类、类型、属性、方法、字段、参数、特性等,主要包括:
●定义表,描述了源代码中定义的类型和成员信息,主要包括:TypeDef、MehodDef、FieldDef、ModuleDef、PropertyDef等。
●引用表,描述了源代码中引用的类型和成员信息,引用元素可以是同一程序集的其他模块,也可以是不同程序集的模块,主要包括:AssemblyRef、TypeRef、ModuleRef、MethodsRef等。
●指针表,使用指针表引用未知代码,主要包括:MethodPtr、FieldPtr、ParamPtr等。
●堆,以stream的形式保存的信息堆,主要包括:#String、#Blob、#US、#GUIDe等。
元数据是保存了类型的编译后数据,是.NET程序运行的基础,我们可以在运行时动态地以反射的方式获取元数据信息,而这些信息在.NET Framework中以System.Type、MethodInfo等封装。
程序集是 .net 应用程序的部署单元。.net应用程序包含一个或多个程序集。通常拓展名是exe或dll的 .net可执行文件被称为程序集。程序集包含了描述程序集的元数据。
开发的代码(一个一个的类)经过编译后会编译成程序集(dll/exe),程序集可以在操作系统上运行,如果要查看自己的代码可以在开发工具上查看,但是要在程序运行过程中查看别的程序集(非自己开发,没有源代码),可以通过反射查看该类中包含的成员,当然也可以查看自己类中包含的成员。
源代码生成程序集,使用反射技术,通过程序集查看包含的成员。
Type:每个类中都有一个对应的Type对象,保存了类中的信息,比如方法、成员等等。
namespace Reflections
{
class MyClass
{
//成员变量,字段
private int A;
private string B;
public int C;
public string D;
//属性
public string Name { get; set; }
public int Number { get; set; }
private int sex { get; set; }
//方法
public void Test1() { }
public int Test2(int number)
{
return number + 1;
}
private void x() { }
}
}
class Program
{
static void Main(string[] args)
{
//Type获取方式
Type t = typeof(MyClass); //方式一 通过类名获取
MyClass myClass = new MyClass();
Type type = myClass.GetType(); //方式二 通过类的对象获取
Console.WriteLine(t.Name); //获取类名 MyClass
Console.WriteLine(t.Namespace);//获取命名空间名 Reflections
Console.WriteLine(t.Assembly);//获取程序集属性说明 Reflections, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Console.WriteLine("\n");
//获取字段
FieldInfo[] fis = t.GetFields();
foreach(FieldInfo field in fis) //只能获取公有字段 field.Name 获取字段名称,field.FieldType 获取字段类型
{
Console.WriteLine(field.Name+" "+field.FieldType); // C System.Int32
// D System.String
}
//获取属性
PropertyInfo[] pas = t.GetProperties();
foreach (PropertyInfo pro in pas) //只能获取公有属性 pro.Name 获取属性名称,pro.FieldType 获取属性类型
{
Console.WriteLine(pro.Name + " " + pro.PropertyType); // Name System.String
//Number System.Int32
}
//获取方法
MethodInfo[] mes = t.GetMethods();
foreach (MethodInfo method in mes) //只能获取公有方法 method.Name 获取方法名称,method.ReturnType 获取方法返回类型
{
Console.WriteLine(method.Name + " " + method.ReturnType);
/* Test1 System.Void
Test2 System.Int32
GetType System.Type
ToString System.String
Equals System.Boolean
GetHashCode System.Int32 同时也可以获取到继承父类的方法
*/
}
}
}
加载程序集方法:
特性(类似批注)
系统特性:
Obsolete 弃用
Conditional("name") 条件特性,控制某一方法是否启用,与宏相对应。name为宏的名字。
#define IsShowMessage
定义了宏,所有调用该方法的地方都会被调用。
没有定义宏,所有调用该方法的地方都不会被调用。
调用者信息特性,用在参数上
调用者信息特性可以访问文件路径,代码行数,调用成员的名称等源代码信息。
这三个特征名称分别为:
CallerFilePath,CallerLineNumber, CallerMemberName
这三个特性只用用于方法中的参数
//这三个参数是系统进行定义和传递的
static void PrintOut(string str,
[CallerFilePath]string fileName = "", //初始化
[CallerLineNumber]int lineNumber = 0,
[CallerMemberName]string methodName = "")
{
Console.WriteLine(str);
Console.WriteLine(fileName);
Console.WriteLine(lineNumber);
Console.WriteLine(methodName);
}
static void main()
{
PrintOut("123"); //所在行为37行
}
//输出为:
//123
//C:\xx\xx\xx\xx\Program.cs 调用该方法的文件的路径名
//37 调用该函数语句所在的行
//Main 调动该方法的成员名称
DebuggerStepThrough debug特性,在方法前面使用,debug调试时不会进入
也可以自定义特性。
标签:反射,Console,Name,程序,System,特性,获取,WriteLine From: https://www.cnblogs.com/Joyce-mi7/p/16921347.html