特性与 DLL 调用
理解特性(Attribute)的作用与自定义
掌握反射基础用法
掌握 DllImport 调用系统 DLL
核心讲解
(1)特性 Attribute
给代码元素(类、方法、属性)添加额外元数据,运行时可以读取。
本质:继承 Attribute 的类
用法:
[特性名(参数)]标记在目标上方常用系统特性:
[Obsolete]过时、[Serializable]可序列化、[Conditional]条件编译
(2)自定义特性
继承
Attribute约定以 Attribute 结尾命名
用
AttributeUsage标记可以用在什么地方
(3)反射
运行时读取元数据、动态创建对象、调用方法。
获取类型:
typeof(类名)、obj.GetType()获取成员:
GetProperties()、GetMethods()、GetCustomAttributes()动态创建:
Activator.CreateInstance()动态调用:
method.Invoke(对象, 参数)
(4)DLL 调用(P/Invoke)
调用 Windows 系统 DLL 里的非托管 API,比如 Win32 API。
关键字:
[DllImport("dll名")]声明外部静态方法
常用:user32.dll、kernel32.dll
操作步骤
自定义一个信息特性
用反射读取特性
调用 user32.dll 弹出消息框
运行验证
代码示例
using System.Reflection;
using System.Runtime.InteropServices;
// ===== 1. 自定义特性 =====
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class InfoAttribute : Attribute
{
public string Author { get; set; }
public string Version { get; set; }
public string Description { get; set; }
public InfoAttribute(string author, string version)
{
Author = author;
Version = version;
}
}
// 标记特性
[Info("张三", "1.0.0", Description = "测试类")]
public class TestClass
{
[Info("李四", "1.1.0", Description = "测试方法")]
public void TestMethod()
{
}
}
// ===== 2. 反射读取特性 =====
Type type = typeof(TestClass);
InfoAttribute? classAttr = type.GetCustomAttribute<InfoAttribute>();
Console.WriteLine("类信息:");
Console.WriteLine($"作者:{classAttr?.Author},版本:{classAttr?.Version},描述:{classAttr?.Description}");
MethodInfo method = type.GetMethod("TestMethod")!;
InfoAttribute? methodAttr = method.GetCustomAttribute<InfoAttribute>();
Console.WriteLine("\n方法信息:");
Console.WriteLine($"作者:{methodAttr?.Author},版本:{methodAttr?.Version}");
// ===== 3. 反射动态创建调用 =====
object? obj = Activator.CreateInstance(type);
method.Invoke(obj, null);
// ===== 4. 调用Win32 DLL =====
class Win32
{
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);
}
// 调用弹出消息框
Win32.MessageBox(IntPtr.Zero, "这是调用DLL弹出的消息", "提示", 0);
Console.ReadKey();
常见误区
特性名不写后缀:使用时可以省略 Attribute 后缀,定义时类名要加 Attribute
反射性能差:反射有性能损耗,频繁调用要缓存,不要滥用
DLL 类型不匹配:32 位 DLL 不能在 64 位程序调用,参数类型要对应
乱用特性:特性是元数据,不要当业务逻辑用
课后练习
自定义一个验证特性,限制字符串长度
用反射遍历一个类的所有属性和方法
调用 kernel32.dll 的 API 获取系统目录
思考:反射有什么优缺点?

