2019年 7月12日 自己练习C#的反射
---恢复内容开始---
1.反射时候 只有GetMembers默认返回公共成员 就是定义public可以去返回 其他私有的 和保护的则不可以
2.在GetMembers里边写上BindingFlags就是可以获取其他的成员 包括私有的 和 可保护的 中间用|号隔开 BindingFlags.NonPublic 就是指定非公共成员也在搜索中 BindingFlags.Instance 指定实例成员也在搜索中
3.只关注该类成员 BindingFlags.DeclaredOnly 不关注其父类成员
static void Main(string[] args) { Type t = typeof(ReClass); Func<MemberTypes, string> getType = (x) => { switch (x) { case MemberTypes.Field: { return "字段"; } case MemberTypes.Method: { return "方法"; } case MemberTypes.Property: { return "属性"; } default: { return "未知"; } } }; MemberInfo[] minfos = t.GetMembers(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach (MemberInfo minfo in minfos) { Console.WriteLine(minfo.Name+"类型"+getType(minfo.MemberType)); } Console.Read(); } public class ReClass { private int _test3; private int _test1 { get; set; } protected int Test2 { get; set; } public int Test3 { get; set; } public void show() { } public static void Show2() { } public static void Show3() { } }
以上代码 就是先定义一个自己的类 然后进行反射 利用Type 进行 第二行 代码 为循环遍历 返回类型 有四个类型 为 方法 属性 字段 未知 第三行为要实现的 因为GetMembers默认返回公共成员 而我们要添加几个 让它全部进行返回 然后就是进行循环遍历 全都显示 出来 前边为名字 后边为属性 获取他们为什么类型对的关键字为GetMembers
Type t = typeof(ReClass); MemberInfo[] minfos = t.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach (FieldInfo minfo in minfos) { Console.WriteLine("字段名称:{0} 字段类型:{1}",minfo.Name,minfo.FieldType.ToString()); }
这里是获取他们的数据类型 具体关键字为GetFields 可以获取他们的数据类型
Type t = typeof(ReClass);
ReClass rc = new ReClass();
rc.Test3 = 3;
FieldInfo[] finfos = t.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
foreach (FieldInfo minfo in finfos)
{
Console.WriteLine("字段名称:{0} 字段类型:{1} rc中的值为{2}",minfo.Name,minfo.FieldType.ToString(),minfo.GetValue(rc));
}
Console.Read();
这段代码为获取他们的值 先实例化那个类 然后为第三个进行赋值 值为3 然后 就是依然的不为公共的获取不出来 那么我们就 添加 类型 然后 遍历循环 输出他们的名称 类型 最后输出 值
Type t = typeof(ReClass); ReClass rc = new ReClass(); rc.Test3 = 3; FieldInfo[] finfos = t.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach (FieldInfo minfo in finfos) { minfo.SetValue(rc,100); Console.WriteLine("字段名称:{0} 字段类型:{1} rc中的值为{2}",minfo.Name,minfo.FieldType.ToString(),minfo.GetValue(rc)); }
这里同上 依然是 只不过变化的是 在遍历循环里边 赋值了100 因为是在循环里边进行赋值 所有他们的值都是100
Type t = typeof(ReClass); ReClass rc = new ReClass(); rc.Test3 = 3; PropertyInfo[] finfos = t.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach (PropertyInfo minfo in finfos) { MethodInfo getinfo = minfo.GetGetMethod(true); Console.WriteLine("get方法名称:{0} 返回值类型:{1} 参数数量{2} MSIL代码长度{3} 局部变量数量{4}", getinfo.Name, getinfo.ReturnType.ToString(), getinfo.GetParameters().Count(), getinfo.GetMethodBody().GetILAsByteArray().Length, getinfo.GetMethodBody().LocalVariables.Count); MethodInfo setinfo = minfo.GetSetMethod(true); Console.WriteLine("get方法名称:{0} 返回值类型:{1} 参数数量{2} MSIL代码长度{3} 局部变量数量{4}", setinfo.Name, setinfo.ReturnType.ToString(), setinfo.GetParameters().Count(), setinfo.GetMethodBody().GetILAsByteArray().Length, setinfo.GetMethodBody().LocalVariables.Count); setinfo.Invoke(rc, new object[] { 123 }); object obj = getinfo.Invoke(rc, null); Console.WriteLine("方法名:{0} 内部值{1}", minfo.Name, obj);
这里循环每个属性 通过GetGetMethod 获取get方法 调用该方法时如果传入true则无法获取不公开的get方法 通过GetSetMethod获取get方法 调用该方法时如果传入true则无法获取不公开的set方法
接着我们输出了该方法的返回类型和参数数量和MSIL代码长度以及局部变量的数量 最后调用了set方法将值改变,然后再通过调用get方法获取这个属性的值
ReClass rc = new ReClass();
rc.Test3 = 3;
MethodInfo[] finfos = t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
foreach (MethodInfo minfo in finfos)
{
if(minfo.GetParameters().Count()>0&&minfo.GetParameters()[0].ParameterType==typeof(string))
{
object obj = minfo.Invoke(rc, new[] { "123" });
MethodBody mbody = minfo.GetMethodBody();
Console.WriteLine("拥有参数的方法名:{0} 返回值类型:{1} 参数1类型:{2} 参数1名称{3} 方法调用后的返回的值{4}",
minfo.Name, minfo.ReturnType.ToString(), minfo.GetParameters()[0].ParameterType.ToString(), minfo.GetParameters()[0].Name, obj.ToString());
else
{
MethodBody mbody = minfo.GetMethodBody();
Console.WriteLine("没有参数的方法名:{0} 返回值类型:{1}", minfo.Name, minfo.ReturnType.ToString());
}
}
{
private int _test3;
private int _test1 { get; set; }
protected int Test2 { get; set; }
public int Test3 { get; set; }
public string show(string s)
{
string a;
return s;
}
public static void Show2()
{
public static string Show3(string s)
{
int b;
int c;
return s;
}
}
改代码 在方法里边写入参数 然后在上边判断是否有参数 遍历循环输出 是否有参数 返回值类型 然后有参数的再输出 第一个参数类型 第一个参数名称 方法调用后的返回值
---恢复内容结束---