百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

C#自学——反射(Reflection)

csdh11 2025-03-06 13:53 14 浏览

反射是很多框架都用到的东西,是从0.25到0.5的一个进阶

反射可以动态创建对象,动态赋值,动态调用方法

反射可以在运行时获得类的信息

每个类都有一个 type对象,构造方法对应的是 ConstructorInfo对象,方法对应的是 MethodInfo对象,字段对应的是 FieldInfo对象,属性对应的是 PropertyInfo对象,使用时需要引用using System.Reflection;

Type

class Dog:Animal
{
  public string name;
  public int age;
  double price;
  static double weight;
  public Dog() { }
  public Dog(string name) { }
  public Dog(string name,int age) { }

  public override void Say() { }

  public double Price { get; set; }
  public double Weight { get; set; }
}

class Animal
{
  public virtual void Say() { }
}

class Print
{
  static void Main()
  {
    Dog dog = new Dog();

    // 获取类的 type 对象常用的三种方式
    Type type = typeof(Dog);
    Type type1 = dog.GetType();
    Type type2 = Type.GetType("Application.Dog");

    //假设只知道类的名字,利用类名创建对象实例
    Type t = typeof(Dog);
    // Activator.CreateInstance(t); 被实例化的对象必须有无参构造方法,没有则会抛出 MissingMethodException 缺失方法异常
    object dog1 = Activator.CreateInstance(t); // 相当于 new Dog();,由于返回的是 object ,所以只能用 object 接收

    Console.WriteLine(dog1);
    Console.WriteLine(t.BaseType); // 获取父类
    Console.WriteLine(t.Name); // 获取类名
    Console.WriteLine(t.FullName); // 获取全名,包含命名空间
    Console.WriteLine(t.IsAbstract); // 判断是否为 抽象类
    Console.WriteLine(t.IsArray); // 是否为 数组
    Console.WriteLine(t.IsClass); // 是否为 普通类
    Console.WriteLine(t.IsEnum); // 是否为 枚举
    Console.WriteLine(t.IsPublic); // 是否为 public
    Console.WriteLine(t.IsValueType); // 是否为 值类型
    Console.WriteLine("------------* 构造方法 *---------------");

    // 获取无参构造方法 t.GetConstructor(new Type[0]); 参数要求是 type对象数组,因此无参构造就只需要入参长度为 0 的数组就好了
    ConstructorInfo c1 = t.GetConstructor(new Type[0]);
    Console.WriteLine(c1); // Void .ctor ctor是IL里面构造方法的表现方式

    // 获取参数类型为 string 的构造方法
    c1 = t.GetConstructor(new Type[] { typeof(string) });
    Console.WriteLine(c1);

    // 获取参数类型为 string,int 的构造方法
    c1 = t.GetConstructor(new Type[] { typeof(string), typeof(int) });
    Console.WriteLine(c1);
    Console.WriteLine("------------* 字段 *---------------");

    // 获取所有字段,必须是public,获取的是未封装的字段
    FieldInfo[] f1 = t.GetFields();
    foreach (var field in f1)
    {
      Console.WriteLine(field);
    }

    // 获取 非public,且 非static 的字段,如果需要获取 static的,把Instance改成static
    f1 = t.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
    foreach (var field in f1)
    {
      Console.WriteLine(field);
    }
    Console.WriteLine("------------* 方法 *---------------");

    // 获得所有方法
    MethodInfo[] m1 = t.GetMethods();
    foreach (var method in m1)
    {
      Console.WriteLine(method);
    }
    // 获得指定方法
    // 注:如果方法有重载,则抛出 AmbiguousMatchException
    MethodInfo m2 = t.GetMethod("Say");
    Console.WriteLine("\n"+m2);
    // 解决方法抛出 AmbiguousMatchException异常
    m2 = t.GetMethod("Say",new Type[0]); // 获取无参方法
    m2 = t.GetMethod("Say",new Type[] { typeof(string)}); // 获取参数为 string 的方法
    Console.WriteLine("------------* 属性 *---------------");

    // 获得属性,获取到的是封装过的属性
    PropertyInfo[] prop = t.GetProperties();
    foreach (var p in prop)
    {
      Console.WriteLine(p);
    }
	}
}

输出:

Application.Dog
Application.Animal
Dog
Application.Dog
False
False
True
False
False
False
------------* 构造方法*---------------
Void.ctor()
Void .ctor(System.String)
Void .ctor(System.String, Int32)
------------* 字段*---------------
System.String name
System.Int32 age
System.Double price
System.Double k__BackingField
System.Double k__BackingField
------------* 方法*---------------
Void Say()
Double get_Price()
Void set_Price(Double)
Double get_Weight()
Void set_Weight(Double)
Boolean Equals(System.Object)
Int32 GetHashCode()
System.Type GetType()
System.String ToString()

Void Say()
------------* 属性*---------------
Double Price
Double Weight

反射示例 1

class Dog
{
  public string name;

  public void Say() { Console.WriteLine("你好,"+Name); }
  public void Say(string name) { Console.WriteLine($"你好,{name}"); }
  public string Name { get; set; }
}

class Print
{
  // 反射示例
  static void Main()
  {
    // 创建对象
    Type t = typeof(Dog);
    object obj = Activator.CreateInstance(t); // 创建对象,调用无参构造(方法1)
    object obj1 = t.GetConstructor(new Type[0]).Invoke(new object[0]); // 获得对象的无参构造,调用(方法2)

    // 给属性赋值
    PropertyInfo prop = t.GetProperty("Name"); // 获得属性
    prop.SetValue(obj, "大宝"); // 赋值

    // 调用方法
    MethodInfo method = t.GetMethod("Say", new Type[0]); // 获得无参方法
    MethodInfo method1 = t.GetMethod("Say", new Type[] { typeof(string) }); // 获得有参方法

    method.Invoke(obj, new object[0]); // 调用无参方法
    method1.Invoke(obj, new object[] { "Tom" }); // 调用有参方法并赋值
  }
}

输出:

你好,大宝
你好,Tom

反射示例 2

class Dog
{
  public string name;

  public void Say() { Console.WriteLine("你好,"+Name); }
  public void Say(string name) { Console.WriteLine($"你好,{name}"); }
  public string Name { get; set; }
}
class Print
{
  static void Main()
  {
    Dog dog = new Dog();
    dog.Name = "Tom";
    Show(dog);
  }

  static void Show(object obj)
  {
    Type t = obj.GetType();

    PropertyInfo[] prop = t.GetProperties();
    foreach (var p in prop)
    {
      if (p.CanRead)
      {
        string name = p.Name;
        object value = p.GetValue(obj);
        Console.WriteLine(name+"="+value);
      }
    }
  }
}

输出:

Name=Tom

反射示例3 (复制对象的值)(浅拷贝--仅复制对象的值,不是同一个对象)

class Dog
{
  public string name;

  public string Name { get; set; }
}
class Print
{
  static void Main()
  {
    Dog dog = new Dog();
    dog.Name = "Tom";
    object dog1 = Clone(dog);
    Console.WriteLine(object.ReferenceEquals(dog,dog1)); // 判断是否为同一个对象
  }

  static object Clone(object obj)
  {
    Type t = obj.GetType();
    object newObject = Activator.CreateInstance(t); // 创建对象

    PropertyInfo[] prop = t.GetProperties();
    foreach (var p in prop)
    {
      if (p.CanRead&&p.CanWrite)
      {
        object value = p.GetValue(obj);
        p.SetValue(newObject, value);
      }
    }
    return newObject;
  }
}

输出:

False

相关推荐

IDEA界面太丑??尝试一下这几个插件

前言IntelliJIDEA主要用于支持Java、Scala、Groovy等语言的开发工具,同时具备支持目前主流的技术和框架,擅长于企业应用、移动应用和Web应用的开发。IntelliJi...

小巧 Vue 页面滚动进度条组件ScrollProgress

今天给大家分享一个轻量级Vue.js全屏滚动进度条组件VueScrollProgress。vue-scroll-progress一款基于vue.js构建的页面滚动进度条组件,...

基于vue实现可视化拖拽编辑器,页面生成工具,提升前端开发效率

项目介绍基于vue实现的可视化拖拽编辑器,实现页面生成工具,提升前端开发效率。可以基层到移动端项目作为自定义json直接生成UI页面。项目特点功能特点...

优秀 vue+heyui 后端管理系统HeyUI-Admin

今天再给小伙伴们推荐一款成熟的企业中后台管理系统HEYUI-Admin。heyui-admin基于vue.js和heyui组件库构建的后台管理系统。包含基础表单/表格功能,拓展组件(图表、富文本编辑...

响应式 Vue.js 前端组件化框架Xvue-UI

今天给小伙伴们推荐一款超不错的Vue轻量级组件框架XVueUI。xvue-ui基于vue2.x构建的响应式前端组件化框架。轻量级、易于上手,提供...

《基于SpringBoot+Vue的在线视频系统设计与实现》开题报告

【计算机毕业设计案例】基于SpringBoot+Vue的在线视频系统设计与实现_哔哩哔哩_bilibili...

超好用 Vue.js 图片裁切组件Vue-ImgCutter

今天给小伙伴们分享一个超棒的Vue图片任意裁剪插件VueImgCutter。vue-img-cutter基于vue2.x构建的轻量级剪切图片组件。支持移动图像、放大缩小图片、任意移动图片、固定比...

Vue 3 进阶用法:异步组件(vue 异步组件原理)

一、代码分割一个大型前端应用,如果所有代码都放在单一文件,体积会特别大,下载时间长,白屏时间久,用户体验差。...

源码补丁神器—patch-package(源码助手怎么用)

作者:张浩一、背景vue项目中使用vue-pdf第三方插件预览pdf,书写业务代码完美运行,pdf文件内容正常预览无问题。后期需求有变,业务需求增加电子签章功能。这个时候pdf文件的内容可以显示出...

经验分享:Vue2 项目升级 Vue3 + Element Plus,借助Deepseek手动升级

Vue3出来好久了,我开发的项目还在使用Vue2框架,一般情况下不考虑升级,但是最近需要接入工作流程引擎之类的,看了下Vue2生态下操作空间不是很好,那索性尝试升级Vue3吧。一番操作下来,升级成功,...

34K Star!史上最全JavaScript资源库 awesome-javascript

34KStar!史上最全JavaScript资源宝库大揭秘引言在GitHub上,有一个备受瞩目的JavaScript资源仓库,以其全面的内容和精心的分类,成为了众多开发者的必备参考。这个拥有超过...

基于 Vue.js 磁片栅格布局组件VueGridLayout

#头条创作挑战赛#今天给大家分享一个超优秀的vue.js拖拽栅格布局插件VueGridLayout。...

6款高颜值 Vue3 PC端UI组件库(vue3开发组件库)

马上到国庆了,还没学习或者想学习vue3的小伙伴们有安排上没?这次推荐几个比较流行的VUE3UI组件库,合理利用,又或者学习借鉴都是不错的选择。1、element-pluselement-plus...

高性能 vue.js+ztree 树形组件Vue-GiantTree

今天给大家分享一款超棒的Vue海量数据渲染树形组件VueGiantTree。vue-giant-tree基于ztree封装的Vue树形组件。轻松实现大数据高性能渲染,适合海量数据渲染场景。zTr...

【推荐】2024年推荐的6款开源免费 Vue 后台管理系统模板,建议收藏

前言在现今的软件开发领域,...