前言
最近想写个类似bash一样可以解析各种命令的小组件,以后要与各种实现命令的类结合使用(在一个应用中使用命令行指令进行操作,因为不想写界面)。一开始设计成用配置文件设置命令项的,但还是觉得既然作为一个组件嵌入,还是做成反射的更方便使用。而且某种程度上来说,这是一种控制反转的模式。
要点
有如下几个技术点需要解决:
- 使用自定义Attribute对需要配置的类和方法标识,此步不在本章讨论范围内;
- 依次获取程序集、类、方法从而收集需要配置的类;
- 通过Type生成实例,并通过MethodInfo调用方法;
详解
通过反射收集信息
获取程序集
获取程序集有如下几种方式:
- 获取所有的程序集:
AppDomain.CurrentDomain.GetAssemblies()
,但这种方式获取的程序集太多,我才两个项目,它就获取了97个Assembly,担心影响性能; - 通过全名获取:
Assembly.Load("longFormName")
,比如Assembly的短名字为Assembly
,一般为Name
属性中获取,全名为System.Reflection.Assembly
,在FullName
中获取,因此其实全名可以理解为带命名空间的名字;
判断类或方法是否被特定Attribute标记
如果是类级别的,需要拿到类的Type对象,并使用类似以下代码获取。
oneType.GetCustomAttribute<CommandAttribute>()
CommandAttribute
是我自己创建的Attribute,如果返回结果为null则证明没有找到。如果是方法级别,需要拿到该方法的MethodInfo,并使用同样的方法去尝试获取有标记的方法,如下所示。
oneMethod.GetCustomAttribute<OptionAttribute>()
,返回null证明没有找到。
生成实例
Activator.CreateInstance(Type)
方法可以得到一个这个Type的实例,你也可以输入它的全名
调用方法
methodInfo.Invoke(instance, new object[] { param1, param2 })
解释下,methodInfo为对应方法的MethodInfo对象,instance为对应类的实例,这两个在通过Attribute去收集信息时我一并存在对象中,方便自己使用。
总结
思路是使用Attribute对类和方法进行标记,然后通过反射将标记的类和方法找出,在需要的时候使用反射进行创建实例和调用方法,如此用户仅需关注自己的逻辑,无需进行什么配置,即使用户对其标记的方法进行了修改(改名、增删参数)都不需要修改额外的代码。而且由于可以在自定义Attribute中收集一些说明性的信息,对于生成、更新帮助文档也十分方便。
网友评论