提供服务器和网站建设,三合一网站建站,腾讯云域名如何建设网站,书生网站在 C# 中#xff0c;反射#xff08;Reflection#xff09;和特性#xff08;Attributes#xff09;是两个强大的功能#xff0c;它们在运行时提供元编程能力#xff0c;广泛用于框架开发、对象映射和动态行为扩展。以下是对它们的详细介绍#xff0c;包括定义、用法、…在 C# 中反射Reflection和特性Attributes是两个强大的功能它们在运行时提供元编程能力广泛用于框架开发、对象映射和动态行为扩展。以下是对它们的详细介绍包括定义、用法、示例和应用场景。 一、反射Reflection
什么是反射
反射是 C# 运行时的一种机制允许程序在运行时动态检查和操作类型、对象及其元数据如类、方法、属性等。通过反射开发者可以
获取类型信息如类名、方法名。动态创建对象。调用方法或访问属性/字段。检查或修改私有成员需注意权限。
反射的核心类库位于 System.Reflection 命名空间。 反射的核心类和方法 Type 表示类型的元数据是反射的核心。获取方式 typeof(ClassName)静态获取类型。object.GetType()从实例获取类型。 Assembly 表示程序集可以加载和检查 DLL 或 EXE。 MethodInfo、PropertyInfo、FieldInfo 分别表示方法、属性和字段的元数据。 Activator 用于动态创建对象实例。 示例 1基本反射操作
using System;
using System.Reflection;class Person
{public string Name { get; set; }private int age 25;public void SayHello(){Console.WriteLine($Hello, Im {Name}, {age} years old.);}
}class Program
{static void Main(){// 获取类型Type type typeof(Person);Console.WriteLine($类名: {type.Name});// 创建实例object instance Activator.CreateInstance(type);// 设置属性PropertyInfo nameProp type.GetProperty(Name);nameProp.SetValue(instance, Alice);// 获取私有字段并修改FieldInfo ageField type.GetField(age, BindingFlags.NonPublic | BindingFlags.Instance);ageField.SetValue(instance, 30);// 调用方法MethodInfo method type.GetMethod(SayHello);method.Invoke(instance, null);// 输出所有公共方法Console.WriteLine(\n公共方法:);foreach (MethodInfo m in type.GetMethods(BindingFlags.Public | BindingFlags.Instance)){Console.WriteLine(m.Name);}}
}输出
类名: Person
Hello, Im Alice, 30 years old.公共方法:
get_Name
set_Name
SayHello
ToString
Equals
GetHashCode
GetType说明
typeof获取 Person 的类型信息。Activator.CreateInstance动态创建实例。GetProperty 和 SetValue访问和修改属性。GetField通过 BindingFlags 获取私有字段。Invoke动态调用方法。 示例 2加载程序集
using System;
using System.Reflection;class Program
{static void Main(){// 加载当前程序集Assembly assembly Assembly.GetExecutingAssembly();foreach (Type type in assembly.GetTypes()){Console.WriteLine($类型: {type.FullName});}}
}输出
类型: Program说明
Assembly.GetExecutingAssembly获取当前程序集。GetTypes列出程序集中所有类型。 反射的优缺点
优点 动态性运行时决定行为适合插件系统或框架。灵活性无需提前知道类型即可操作。 缺点 性能开销反射比直接调用慢。安全性可能暴露私有成员需谨慎使用。 二、特性Attributes
什么是特性
特性是 C# 中的一种声明性标签用于为代码元素如类、方法、属性等附加元数据。特性在运行时可以通过反射读取用于控制行为或提供额外信息。
特性定义在 System 命名空间中常用基类是 Attribute。 特性的定义与使用 定义特性 继承自 Attribute添加 [AttributeUsage] 指定适用范围。 应用特性 使用方括号 [ ] 标记在代码元素上。 读取特性 通过反射的 GetCustomAttributes 方法获取。 示例 1自定义特性
using System;
using System.Reflection;// 定义特性
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple false)]
public class DescriptionAttribute : Attribute
{public string Description { get; }public DescriptionAttribute(string description){Description description;}
}// 使用特性
[Description(这是一个测试类)]
class TestClass
{[Description(这是一个测试方法)]public void TestMethod(){Console.WriteLine(Hello from TestMethod!);}
}class Program
{static void Main(){// 获取类特性Type type typeof(TestClass);DescriptionAttribute classAttr (DescriptionAttribute)Attribute.GetCustomAttribute(type, typeof(DescriptionAttribute));Console.WriteLine($类描述: {classAttr?.Description});// 获取方法特性MethodInfo method type.GetMethod(TestMethod);DescriptionAttribute methodAttr (DescriptionAttribute)method.GetCustomAttribute(typeof(DescriptionAttribute));Console.WriteLine($方法描述: {methodAttr?.Description});// 调用方法object instance Activator.CreateInstance(type);method.Invoke(instance, null);}
}输出
类描述: 这是一个测试类
方法描述: 这是一个测试方法
Hello from TestMethod!说明
[AttributeUsage]限制特性只能用于类和方法且不可重复。GetCustomAttribute获取指定类型的特性实例。Description特性中存储的元数据。 示例 2内置特性 - [Obsolete]
using System;class Program
{[Obsolete(此方法已过时请使用 NewMethod, false)] // false 表示警告true 表示错误static void OldMethod(){Console.WriteLine(Old Method);}static void NewMethod(){Console.WriteLine(New Method);}static void Main(){OldMethod(); // 编译器会发出警告NewMethod();}
}输出带警告
Old Method
New Method说明
[Obsolete]标记方法为过时编译时提示开发者。 特性的应用场景 框架开发 ASP.NET Core 使用 [Route]、[HttpGet] 等特性定义路由和行为。Entity Framework 使用 [Table]、[Key] 配置数据库映射。 验证与描述 [Required]、[MaxLength] 用于数据验证。[Description] 添加文档信息。 条件编译 [Conditional(DEBUG)] 在特定条件下执行方法。 反射与特性的结合
反射和特性经常一起使用例如
依赖注入通过反射扫描带有特定特性的类动态注入。序列化检查 [Serializable] 或自定义特性决定序列化字段。 优缺点
优点 声明式编程减少硬编码提高可维护性。元数据丰富为工具和框架提供信息。 缺点 运行时开销读取特性需要反射。复杂度过度使用可能使代码难以理解。 总结
反射运行时动态操作类型和对象适合需要灵活性的场景如插件系统。特性为代码添加元数据配合反射实现声明式逻辑如框架配置。
通过反射你可以动态调用方法或创建实例通过特性你可以为代码附加规则或描述。这两者在 C# 中是构建高级功能如 ORM、AOP的基石。