什么是反射
反射是一种在运行时分析和操作程序结构的能力。它允许程序在运行时获取关于类、对象、方法、属性等的信息,并且可以在运行时动态地调用方法、创建对象、访问属性等。
反射的优缺点
- 优点:提高了程序的灵活性和扩展性,降低耦合度
- 缺点:由于反射多了一道程序,性能上相较于直接代码要慢
基础认识
(1)Assembly:定义和加载程序集,加载在程序集中的所有模块以及从此程序集中查找类型并创建该类型的实例。
(2)Module:获取包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
(3)ConstructorInfo:获取构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(4)MethodInfo(GetMethod/GetMethods):获取方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(5)FiedInfo(GetField/GetFields):获取字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
(6)EventInfo(GetEvent/GetEvents):获取事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
(7)PropertyInfo(GetProperty/GetProperties):获取属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
(8)ParameterInfo:获取参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。
(9)MemberInfo(GetMember/GetMembers):获取字段、事件、属性等各种信息
使用
- 动态获取数据库表
/// <summary> /// 动态连接数据库 /// </summary> /// <param name="optionsBuilder"></param> protected override void OnModelCreating(ModelBuilder modelBuilder) //ModelBuilder操作数据上下文类 { var assmbly = Assembly.GetAssembly(typeof(User)); //Assembly.GetAssembly:获取该程序集中的所有类型。 var types = assmbly.GetTypes(); foreach (var item in types) { //判断type是不是继承于EntityBase(审计表) 和 基类不能成为表(基类改成抽象类) if (typeof(EnTityBase).IsAssignableFrom(item) && !item.IsAbstract) { var builder = modelBuilder.Entity(item); var table = item.GetCustomAttribute<TableAttribute>(); if (table != null) { //ToTable 方法接受一个字符串参数,用于指定表名。 builder.ToTable(table.Name); } } } base.OnModelCreating(modelBuilder); }
- 动态获取服务端URL路径
var list = new List<PermDto>(); //获取程序集 var assembly = Assembly.GetAssembly(typeof(PermController)); //获取类型 var types = assembly.GetTypes(); foreach (var type in types) { //筛选控制器 if (typeof(ControllerBase).IsAssignableFrom(type)) { //获取控制器的所有方法 var methods = type.GetMethods(); //获取自定义的名 foreach (var method in methods) { //GetCustomAttribute获取它的自定义特性 var arrt = method.GetCustomAttribute<PermissonDescAttribute>(); if (arrt != null) { var name = arrt.Name; var url = $"/api/{type.Name.Replace("Controller", "")}/{method.Name}"; list.Add(new PermDto { PermName = name, CollerName = type.Name.Replace("Controller", ""), ActionName = url, }); } } } }
上面此方法是可以直接获取服务端url,如需添加到数据库,实现自动化添加数据库,可以设置一个 中间件进行添加
当然,上面的方法还不足以获取url,则需要在控制器当中,定义一个PermissonDescAttribute
(自定义特性),其可以作用于方法上,该特性包含一个name属性,用来描述名称
//AttributeUsage:使用范围
[AttributeUsage(AttributeTargets.Method)]
public class PermissonDescAttribute : Attribute
{
//name是一个只读的string属性,用来存储特性的名称
public string Name { get; }
//特性类的构造函数,接收一个string类型的参数name,并赋值给name
public PermissonDescAttribute(string name)
{
Name = name;
}
}
控制器方法名上去声明这个自定义特性
就此获取到url,但是再此用到了特性,从而去了解一下特性是何。