导读:本期聚焦于小伙伴创作的《C#怎么使用反射机制 C#如何用Reflection动态获取类型信息和调用方法属性》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#怎么使用反射机制 C#如何用Reflection动态获取类型信息和调用方法属性》有用,将其分享出去将是对创作者最好的鼓励。

C#的反射机制是.NET框架提供的重要功能,位于System.Reflection命名空间下,它让程序可以在运行时检查、操作和修改自身的元数据和行为,不需要在编译时就确定要操作的具体类型。反射在很多场景都能发挥作用,比如插件化开发、序列化反序列化、依赖注入框架的实现等。

C#怎么使用反射机制 C#如何用Reflection动态获取类型信息和调用方法属性

反射的基础:获取Type对象

要使用反射操作类型,首先需要获取对应类型的Type对象,这是反射的入口。Type类包含了类型的所有元数据信息,比如类名、基类、实现的接口、成员列表等。获取Type对象有三种常用方式:

  • 通过对象的GetType()方法获取,适用于已经有类型实例的场景
  • 通过typeof()运算符获取,适用于编译时已知类型的场景
  • 通过Type.GetType()静态方法获取,传入类型的完全限定名,适用于运行时才知道类型名称的场景

下面是对应的代码示例:

using System;

namespace ReflectionDemo
{
    public class User
    {
        public string Name { get; set; }
        public int Age { get; set; }
        
        public void SayHello()
        {
            Console.WriteLine($"Hello, I am {Name}, {Age} years old");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            User user = new User();
            // 方式1:通过实例的GetType方法获取Type
            Type type1 = user.GetType();
            Console.WriteLine($"方式1获取的类型名:{type1.Name}");
            
            // 方式2:通过typeof运算符获取Type
            Type type2 = typeof(User);
            Console.WriteLine($"方式2获取的类型名:{type2.Name}");
            
            // 方式3:通过Type.GetType方法获取Type,需要传入完全限定名
            Type type3 = Type.GetType("ReflectionDemo.User");
            Console.WriteLine($"方式3获取的类型名:{type3.Name}");
        }
    }
}

动态获取类型的成员信息

获取到Type对象之后,就可以通过它的属性和方法获取类型的各种成员信息,包括构造函数、属性、方法、字段、事件等。常用的获取成员的方法如下:

  • GetConstructors():获取类型的所有公共构造函数
  • GetProperties():获取类型的所有公共属性
  • GetMethods():获取类型的所有公共方法
  • GetFields():获取类型的所有公共字段

下面的代码演示了如何获取User类的所有属性和方法信息:

using System;
using System.Reflection;

namespace ReflectionDemo
{
    public class User
    {
        public string Name { get; set; }
        public int Age { get; set; }
        
        public void SayHello()
        {
            Console.WriteLine($"Hello, I am {Name}, {Age} years old");
        }
        
        private void PrivateMethod()
        {
            Console.WriteLine("This is a private method");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Type userType = typeof(User);
            
            // 获取所有公共属性
            PropertyInfo[] properties = userType.GetProperties();
            Console.WriteLine("公共属性列表:");
            foreach (PropertyInfo prop in properties)
            {
                Console.WriteLine($"属性名:{prop.Name},类型:{prop.PropertyType.Name}");
            }
            
            // 获取所有公共方法
            MethodInfo[] methods = userType.GetMethods();
            Console.WriteLine("n公共方法列表:");
            foreach (MethodInfo method in methods)
            {
                Console.WriteLine($"方法名:{method.Name},返回类型:{method.ReturnType.Name}");
            }
        }
    }
}

动态创建类型实例

反射支持在运行时动态创建类型的实例,不需要使用new关键字。常用的方法有两种:

  • 调用无参构造函数:使用Activator.CreateInstance()方法,直接传入Type对象即可
  • 调用有参构造函数:使用Type.GetConstructor()获取对应参数的构造函数,再调用Invoke()方法传入参数创建实例

代码示例:

using System;
using System.Reflection;

namespace ReflectionDemo
{
    public class User
    {
        public string Name { get; set; }
        public int Age { get; set; }
        
        // 无参构造函数
        public User() { }
        
        // 有参构造函数
        public User(string name, int age)
        {
            Name = name;
            Age = age;
        }
        
        public void SayHello()
        {
            Console.WriteLine($"Hello, I am {Name}, {Age} years old");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Type userType = typeof(User);
            
            // 调用无参构造函数创建实例
            User user1 = (User)Activator.CreateInstance(userType);
            user1.Name = "张三";
            user1.Age = 20;
            user1.SayHello();
            
            // 调用有参构造函数创建实例
            // 获取参数为string和int的构造函数
            ConstructorInfo constructor = userType.GetConstructor(new Type[] { typeof(string), typeof(int) });
            // 传入构造参数创建实例
            User user2 = (User)constructor.Invoke(new object[] { "李四", 25 });
            user2.SayHello();
        }
    }
}

动态调用方法和操作属性

反射不仅可以获取成员信息,还可以在运行时动态调用方法、读写属性值,即使这些成员是私有的,也可以通过设置绑定标志来获取和操作。

动态调用方法

调用方法需要先获取MethodInfo对象,然后调用它的Invoke()方法,第一个参数是方法所属的对象实例(静态方法传入null),第二个参数是方法的参数数组。

代码示例:

using System;
using System.Reflection;

namespace ReflectionDemo
{
    public class User
    {
        public string Name { get; set; }
        public int Age { get; set; }
        
        public void SayHello()
        {
            Console.WriteLine($"Hello, I am {Name}, {Age} years old");
        }
        
        public int AddAge(int increment)
        {
            Age += increment;
            return Age;
        }
        
        private void PrivateMethod()
        {
            Console.WriteLine("调用了私有方法");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Type userType = typeof(User);
            User user = new User { Name = "王五", Age = 30 };
            
            // 调用公共无参方法
            MethodInfo sayHelloMethod = userType.GetMethod("SayHello");
            sayHelloMethod.Invoke(user, null);
            
            // 调用公共有参方法
            MethodInfo addAgeMethod = userType.GetMethod("AddAge");
            object result = addAgeMethod.Invoke(user, new object[] { 5 });
            Console.WriteLine($"调用AddAge后的年龄:{result}");
            
            // 调用私有方法,需要指定BindingFlags
            MethodInfo privateMethod = userType.GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
            privateMethod.Invoke(user, null);
        }
    }
}

动态读写属性

操作属性需要先获取PropertyInfo对象,然后通过GetValue()方法读取属性值,通过SetValue()方法设置属性值。

代码示例:

using System;
using System.Reflection;

namespace ReflectionDemo
{
    public class User
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Type userType = typeof(User);
            User user = new User();
            
            // 获取Name属性
            PropertyInfo nameProp = userType.GetProperty("Name");
            // 设置Name属性值
            nameProp.SetValue(user, "赵六");
            // 读取Name属性值
            object nameValue = nameProp.GetValue(user);
            Console.WriteLine($"Name属性值:{nameValue}");
            
            // 获取Age属性
            PropertyInfo ageProp = userType.GetProperty("Age");
            ageProp.SetValue(user, 28);
            object ageValue = ageProp.GetValue(user);
            Console.WriteLine($"Age属性值:{ageValue}");
        }
    }
}

反射的性能影响和优化

反射虽然灵活,但是性能比直接编译调用的代码要低,因为反射需要遍历元数据、进行类型检查等操作。如果需要在高频场景使用反射,可以采取以下优化方式:

  • 缓存TypeMethodInfoPropertyInfo等对象,避免重复获取
  • 对于频繁调用的方法,可以使用表达式树或者Emit生成委托,减少反射调用的开销
  • 非必要场景不要使用反射,优先考虑泛型、接口等编译时多态方案

下面是一个简单的缓存反射对象的示例:

using System;
using System.Collections.Generic;
using System.Reflection;

namespace ReflectionDemo
{
    public class User
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    
    class ReflectionCache
    {
        // 缓存Type对象
        private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
        // 缓存属性信息
        private static readonly Dictionary<Type, PropertyInfo[]> PropertyCache = new Dictionary<Type, PropertyInfo[]>();
        
        public static Type GetTypeFromCache(string typeName)
        {
            if (!TypeCache.ContainsKey(typeName))
            {
                TypeCache[typeName] = Type.GetType(typeName);
            }
            return TypeCache[typeName];
        }
        
        public static PropertyInfo[] GetPropertiesFromCache(Type type)
        {
            if (!PropertyCache.ContainsKey(type))
            {
                PropertyCache[type] = type.GetProperties();
            }
            return PropertyCache[type];
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Type userType = ReflectionCache.GetTypeFromCache("ReflectionDemo.User");
            PropertyInfo[] properties = ReflectionCache.GetPropertiesFromCache(userType);
            Console.WriteLine($"从缓存获取的属性数量:{properties.Length}");
        }
    }
}

反射的实际应用场景

反射在实际开发中有很多典型的应用场景:

  • 插件化开发:主程序通过反射加载外部DLL,动态识别并加载插件类型,不需要主程序依赖插件的具体实现
  • 序列化框架:比如JSON序列化工具,通过反射获取对象的属性信息,将对象转换为JSON字符串,或者将JSON字符串转换为对象
  • 依赖注入容器:容器通过反射解析类型的构造函数和依赖关系,动态创建对象并注入依赖
  • 单元测试框架:测试框架通过反射发现标记了测试特性的方法,动态执行测试用例

合理使用反射可以让代码更加灵活、扩展性更强,但是也要注意不要滥用,避免带来不必要的性能开销和维护难度。

C#Reflection动态获取类型信息调用方法属性修改时间:2026-06-20 17:45:38

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。