在前面的文章中,对反射作了一个小结,当时主要是用来将数据库的数据到处到csv文件中,方便使用excel表格直接打开对应的数据表,这边主要是创建一个DataRecord类,该类中将所有的列的名字和对应的数据类型设成了特性,自定义了一个用于属性的特性。获取所有属性的特性的名字,就能得到对应的列的名字,然后将每条属性赋值,就可以得到一条的数据。
最近在查看自定义特性和反射的一些用法的时候,发现在网上大部分的使用例子都是用于属性,很少有用于类的,或者我查询的范围有点小,不管怎样,想对类自定义特性作一次尝试,其实主要的思想是一致的,主要还是想练练手。
下面是一个简单的例子,主要是实现根据不同权限,在登录成功之后显示相应权限的menuStripButton,并且将button对应的界面一起存放到一个定义好的字典中,能实现这个功能的方法很多,这边使用自定义特性的方法来实现。
由于是直接使用的menuStrip控件,对应的menuStripButton也没法设置权限。在很少按钮的时候,我们可以将所有的界面的实例化,将界面的实例化的对象和按钮存入字典中,然后根据界面对象中的权限属性来remove不符合条件的button,将不符合条件button的visable属性设为false即可,但是如果按钮很多,那对应的界面也有很多,如果还是一个一个实例化,就浪费资源了。我们应该是需要什么界面,就实例化相应的界面对象才是。
先创建一个Attribute类,用于给不同的组件UserControl设置特性,该类中包含2个属性,一个button的Name属性和一个权限属性,如下:
[AttributeUsage(AttributeTargets.Class)]
//设置该特性用于类的类型
public class CustomTestAttribute:Attribute
{
public CustomTestAttribute(string buttonName, string level)
{
ButtonName = buttonName;
Level = level;
}
public string ButtonName{get;set;}
public string Level{get;set;}
}
创建了这样一个特性,如何使用于自定义的UserControl中呢,如下:
[CustomTest("UsersSettings", "UserLevel")]
public class UsersSettingsUserControl:UserControl
{
...
}
这样,该类就具有了CustomTestAttribute特性,接下来就是如何使用该自定义的特性:
static void Main(string[] args)
{
var a = Assembly.Load("自定义的UserControl所在的程序集");
Type[] types = a.GetTypes();
//获取程序集a中所有的类型,其实就包括了UserControl类
foreach(var type in types)
{
//获取存在CustomTestAttribute特性的类,如果具有该特性,则attr不为null
var attr = type.GetCustomAttribute(typeof(CustomTestAttribute));
if(attr != null)
{
var customAttr = attr as CustomTestAttribute;
//如果attr不为null,就是具有该特性的类,attr就是其特性,然后就可以得到该类对应的特性中的按钮名字和权限
string buttonName = customAttr.ButtonName;
string level = customAttr.Level;
... //下面的步骤省略
}
上面我们得到了我们需要的内容:界面对应的类type, 按钮的名字 buttonName, 权限Level,一开始我们打算将创建按钮,对应界面的实例对象的字典,知道了type,使用下面的方法创建实例化对象:
Activator.CreatInstance(type) //就动态可以创建type类的实例
Activator.CreatInstance(type, object[] objects) //创建需要参数初始化的对象。
因为是学习的内容有限,因此上面的例子或许会有很多漏洞,或者有更方便的方法,若是有好心人,希望能够指正。关于Activator的用途还有很多,在了解更多之后再展开总结。