zoukankan      html  css  js  c++  java
  • C#反射技术的简单操作(读取和设置类的属性)

    首先建立一个测试的类 

    复制代码代码如下:

    public class MyClass 

      public int one { set; get; } 
      public int two { set; get; } 
      public int five { set; get; } 
      public int three { set; get; } 
      public int four { set; get; } 


    然后编写反射该类的代码 

    复制代码代码如下:

    MyClass obj = new MyClass(); 
    Type t = typeof(MyClass); 
    //循环赋值 
    int i = 0; 
    foreach (var item in t.GetProperties()) 

      item.SetValue(obj, i, null); 
      i += 1; 

    //单独赋值 
    t.GetProperty("five").SetValue(obj, 11111111, null); 
    //循环获取 
    StringBuilder sb = new StringBuilder(); 
    foreach (var item in t.GetProperties()) 

      sb.Append("类型:" + item.PropertyType.FullName + " 属性名:" + item.Name + " 值:" + item.GetValue(obj, null) + "<br />"); 

    //单独取值 
    int five = Convert.ToInt32(t.GetProperty("five").GetValue(obj, null)); 
    sb.Append("单独取five的值:" + five); 
    string result = sb.ToString(); 
    Response.Write(result); 


    测试显示结果: 
    类型:System.Int32 属性名:one 值:0 
    类型:System.Int32 属性名:two 值:1 
    类型:System.Int32 属性名:five 值:11111111 
    类型:System.Int32 属性名:three 值:3 
    类型:System.Int32 属性名:four 值:4 
    单独取five的值:11111111 

    好了,了解了类的属性反射使用后,聪明的你可能就想到了方法也是可以这样做的,即t.GetProperties()改为t.GetMethods(),操作方法同上。

    1.加载程序集的几种方式

    1.自动扫描当前运行项目的bindebug ,网站是扫描bin目录 下的Lib.dll程序集 (常用)
    1.Assembly.Load("Lib");
    2.指定一个绝对路径加载程序集
    1.Assembly.LoadFile
    2.Assembly.LoadFrom
    3.获得当前 程序域中 所有的Assembly,包括GAC中的程序集
    1.AppDomain.CurrentDomain.GetAssemblies();
    4.可以直接通过this来获取
    1.this.GetType().Assembly;
    5. typeof(Form1).Assembly

    2.获取类的几种方式

    1.获取指定类的类型 ass.GetType("Lib.Pig");
    2.获取当前所有的类(包括公有和非有) ass.GetTypes();
    3.忽略类的全名的大小写 ass.GetType("Lib.pig", false, true);
    4.可以typeof()关键字来获取 typeof(Form1);
    5.可以通过实例的GetType()
    Type type5 = this.GetType(); Form1 f1 = new Form1(); Type type6 = f1.GetType();

    3.操作类中的字段

    1.获取私有字段

    pigtype.GetField("_name", BindingFlags.NonPublic | BindingFlags.Instance);
    BindingFlags.NonPublic | BindingFlags.Instance:表示获取一个非共有的实例字段,一定是组合使用
    BindingFlags.NonPublic | BindingFlags.Static:表示获取一个非共有的静态字段 ,一定是组合使用
    ####2.给_name字段赋值
    object instance = ass.CreateInstance("Lib.Pig");
    nameInfo.SetValue(instance, "八戒");

    3.获取instance中的_name字段值

            object retVal = nameInfo.GetValue(instance);
            MessageBox.Show(retVal.ToString());
    

    4.操作类的方法

    1.获取方法
        pigType.GetMethod("Eat", BindingFlags.Public | BindingFlags.Instance);
    2.调用方法
        mInfo.Invoke(instance, new object[] { "八戒", 500 });
    

    5.实例化对象

    1.     Assembly ass = Assembly.Load("Lib");
         ass.CreateInstance("Lib.Pig");
    2.     Type pigType = ass.GetType("Lib.Pig");
         Activator.CreateInstance(pigType);//要求:必须要求类拥有无参的构造函数,否则报错
    3.     ConstructorInfo cinfo = pigType.GetConstructor(new Type[] { typeof(string) });
        object pigInstance = cinfo.Invoke(new object[] { "八戒11" }); //new Pig("八戒",500)
    4.    /获取pigInstance中的Name的值
        PropertyInfo nameInfo = pigType.GetProperty("Name");
         object res = nameInfo.GetValue(pigInstance)
    

    6.Type类型中重要方法

    Assembly ass = Assembly.Load("Lib");
    Type pigType = ass.GetType("Lib.Pig");
    
    //获取程序集的绝对路径
    //pigType.Assembly.Location
    //pigType .FullName  //Lib.Pig
    //pigType.Name// Pig
    
    //1.0 判断Pig类是否实现了Ipig接口
    //1.0.1 获取IPig接口的Type
    Type ipigType = ass.GetType("Lib.IPig");
    //1.0.2 判断pigType是否实现了ipigType
    bool isok = ipigType.IsAssignableFrom(pigType);  //true
    
    //2.0 判断Pig类是否继承了Basepig类
    Type basepigType = ass.GetType("Lib.BasePig");
    bool isext = pigType.IsSubclassOf(basepigType); //true
    
    //3.0 object instance=new Pig();
    object instance = ass.CreateInstance("Lib.Pig");
    pigType.IsInstanceOfType(instance); //true


    如果在一个类中有一个公有字段,那么在这个类的外部我们可以自由无阻的使用这个字段,但是如果给这个字段赋了一个很“离谱”的值,那这对程序可能会造成很大的影响

    比如:

    Class Student{

       public int Age;

    }

    在这个类外我们写:

    Student stu =new Student();

    stu.Age = 1000;

    众所周知,人目前是不可能活到1000岁的,但是这样赋值编译器又不会报错(假设外部没有限制Age取值的逻辑),但是我们知道这个程序运行后的结果是有错误的

    所以我们有了“属性”这个东西,代码可以这样写:

    class Student{
            private int age;
     
            public int Age
            {
                get return age; }
                set {
                    if (value >= 0 && value <= 100)
                    {
                        age = value;
                    }
                    else
                    {
                        throw new Exception("Age value has error.");
                    }
                }
              }

     这里的value以为上下文关键字了

    属性里的get,set访问器可以对字段提供一些安全保护了(个人理解为使用一些逻辑来保护字段的值为“说的过去的”)

    ---------------------------------------------------------------------------------------------------------------

    ---------------------------------------------------------------------------------------------------------------

    一段总结:

    //属性对外:暴露数据,数据可以是存储在字段里的,也可以是动态计算出来的

    //对内:保护字段不受“非法值”污染

    //一般情况下,它们都用于表示实体(对象或类型)的状态

    //属性大多数情况下是字段的包装器(wrapper)

    //建议:永远使用属性(而不是字段)来暴露数据,即字段永远是private或protected的

  • 相关阅读:
    Hbase学习记录(2)| Shell操作
    Hbase学习记录(1)|伪分布式安装
    Zookeeper集群安装详解
    防范xss的正确姿势
    怎么样通过编写Python小程序来统计测试脚本的关键字
    XSS报警机制(前端防火墙:第二篇)
    XSS姿势——文件上传XSS
    MySQL防范SQL注入风险
    SQL注入—我是如何一步步攻破一家互联网公司的
    通过BurpSuite和sqlmap配合对dvwa进行sql注入测试和用户名密码暴力破解
  • 原文地址:https://www.cnblogs.com/Alex80/p/13293147.html
Copyright © 2011-2022 走看看