[原创]通过Attribute完成中文智能提示
2009-07-29 14:10 水随风 阅读(350) 评论(1) 编辑 收藏 举报前言
Attribute作为”特性”,可运用的范围是很广的,而且运用的场景也是非常的灵活。Attribute在MSDN中是这样解释的(有删减):
Attribute 类将预定义的系统信息或用户定义的自定义信息与目标元素相关联。目标元素可以是程序集、类、构造函数、委托、枚举、事件、字段、接口、方法、可移植可执行文件模块、参数、属性 (Property)、返回值、结构或其他属性 (Attribute)。
所有属性类型都直接或间接地从 Attribute 类派生。属性可应用于任何目标元素;多个属性可应用于同一目标元素;并且属性可由从目标元素派生的元素继承。
如果在实际场景中使用Attribute呢?可以看到,在很多的组件编写时,会在属性前面加上一些特定的Attribute,之后就可以在设计界面的属性设计器中看到。
场景
在一些大型的桌面系统开发中,会重构出很多的基础控件。这些强大的基础控件,进而构造出非常复杂的画面,实际上这些画面也有很多的共性,所以又会抽出基础Form进行继承开发,减少开发业务的复杂度,提高了开发人员的开发效率。
而在一般的大型项目中,会有专门的一块业务,作为”系统管理员”操作的部分。实际上这些”系统管理员”对编程和系统一窍不通,但是他们明白式样,明白简单的逻辑。所以为了提供给他们很好的去操作画面上的控件。提供了一个功能,就是在管理画面将这些控件用中文的形式显示出来,并且属性的访问也用中文的形式,这样他们就可以写出简单的逻辑去管理和维护业务画面。在这里我们就用到了Attribute的强大功能,去完成这个操作。比如:当前台画面上有检索部分和结果显示部分,这部分需要动态进行SQL拼接=>
姓名.文字 != ‘’
{
AND sql1
}
姓名.文字 == ‘’
{
AND sql2
}
实例
首先,我们需要创建一个SomeClassCNAttribute和一个SomePropertyCNAttribute类,用以对开发的控件进行说明,他们都继承于Attribute:
1: public class SomeClassCNAttribute : Attribute
2: {
3: private string _name;
4:
5: public string Name
6: {
7: get { return _name; }
8: set { _name = value; }
9: }
10: public SomeClassCNAttribute(string strName)
11: {
12: _name = strName;
13: }
14: }
15:
16: public class SomePropertyCNAttribute : Attribute
17: {
18: private string _name;
19:
20: public string Name
21: {
22: get { return _name; }
23: set { _name = value; }
24: }
25: public SomePropertyCNAttribute(string strName)
26: {
27: _name = strName;
28: }
29: }
30:
这两个属性是准备用来对说明类库用途的。如:
32: [SomeClassCN("基本信息1")]
33: public class SomePropertyCopy
34: {
35: private string strRealName;
36: [SomePropertyCN("姓名")]
37: public string StrRealName
38: {
39: get { return strRealName; }
40: set { strRealName = value; }
41: }
42: private string strSex;
43: [SomePropertyCN("性别")]
44: public string StrSex
45: {
46: get { return strSex; }
47: set { strSex = value; }
48: }
49: private string strEmail;
50: [SomePropertyCN("邮件")]
51: public string StrEmail
52: {
53: get { return strEmail; }
54: set { strEmail = value; }
55: }
56:
57: public SomePropertyCopy() { }
58:
59: public SomePropertyCopy(string name, string sex, string email)
60: {
61: strRealName = name;
62: strSex = sex;
63: strEmail = email;
64: }
65: }
该类可以通过定义一个FCNExpression类库来读取中英文名并存入字典
根据类来创建一个关于属性与方法的对应中英文的字典,每个类都看作一个树,树下有属性和方法名。
1: /// <summary>
2: /// 单位类,读取后存入表达库
3: /// </summary>
4: public class FCNExpression
5: {
6: #region 字段定义
7: private Type _type;
8: #endregion
9:
10: #region 构造函数
11: protected FCNExpression() { }
12:
13: public FCNExpression(object objTarget)
14: : this(objTarget.GetType())
15: {
16:
17: }
18:
19: public FCNExpression(Type type)
20: : this()
21: {
22: _type = type;
23: }
24: #endregion
25:
26: #region 属性定义
27: private List<ExpressionItem> _innerExpressions = null;
28: /// <summary>
29: /// 内部字典
30: /// </summary>
31: public List<ExpressionItem> InnerExpressions
32: {
33: get
34: {
35: if (_innerExpressions == null)
36: {
37: _innerExpressions = GetSomePropertyAttributesDirecs(_type);
38: }
39: return _innerExpressions;
40: }
41: }
42: /// <summary>
43: /// 中文类名
44: /// </summary>
45: public string ClassCNName
46: {
47: get
48: {
49: if (_type.IsDefined(typeof(SomeClassCNAttribute), false))
50: {
51: SomeClassCNAttribute sccna =
52: Attribute.GetCustomAttribute(_type, typeof(SomeClassCNAttribute)) as SomeClassCNAttribute;
53: return sccna.Name;
54: }
55: return string.Empty;
56: }
57: }
58: #endregion
59:
60: #region 方法定义
61: /// <summary>
62: /// 取得定义为SomeProperty的属性
63: /// </summary>
64: /// <param name="objTarget"></param>
65: private List<ExpressionItem> GetSomePropertyAttributesDirecs(Type objType)
66: {
67: if (objType == null)
68: {
69: return null;
70: }
71: List<ExpressionItem> _dicExpressions = new List<ExpressionItem>();
72: //当前类型内定义的属性。
73: foreach (PropertyInfo pinfo in objType.GetProperties())
74: {
75: //循环查找是否定义过SomePropertyCNAttribute属性。
76: if (pinfo.IsDefined(typeof(SomePropertyCNAttribute), false))
77: {
78: //将当前属性所定义的Attribute取得,读取定义名称,存入键值对。
79: SomePropertyCNAttribute spcna =
80: Attribute.GetCustomAttribute(pinfo, typeof(SomePropertyCNAttribute)) as SomePropertyCNAttribute;
81: ExpressionItem eiNew = new ExpressionItem();
82: eiNew.sCnName = spcna.Name;
83: eiNew.sEnName = pinfo.Name;
84: eiNew.ItemType = MemberTypes.Property;
85: if (_dicExpressions.Contains(eiNew))
86: {
87: continue;
88: }
89: //存入中文与属性名 eg.<姓名,strName>
90: _dicExpressions.Add(eiNew);
91: }
92: }
93: foreach (MethodInfo minfo in objType.GetMethods(BindingFlags.Public))
94: {
95: //循环查找是否定义过SomePropertyCNAttribute属性。
96: if (minfo.IsDefined(typeof(SomeClassCNAttribute), false))
97: {
98: //将当前属性所定义的Attribute取得,读取定义名称,存入键值对。
99: SomeClassCNAttribute spcna =
100: Attribute.GetCustomAttribute(minfo, typeof(SomeClassCNAttribute)) as SomeClassCNAttribute;
101: ExpressionItem eiNew = new ExpressionItem();
102: eiNew.sCnName = spcna.Name;
103: eiNew.sEnName = minfo.Name;
104: eiNew.ItemType = MemberTypes.Method;
105: if (_dicExpressions.Contains(eiNew))
106: {
107: continue;
108: }
109: //存入中文与属性名 eg.<姓名,strName>
110: _dicExpressions.Add(eiNew);
111: }
112: }
113: return _dicExpressions;
114: }
115: /// <summary>
116: /// 获取属性的值
117: /// </summary>
118: /// <param name="strCNName">中文名称</param>
119: /// <param name="objTarget">目标对象,获取该对象下的属性值</param>
120: /// <param name="index">索引,如果是集合的情况下用索引查找</param>
121: /// <returns>Value值</returns>
122: public object GetPropertyValueByCNName(string strCNName, object objTarget, params object[] index)
123: {
124: Type objType = objTarget.GetType();
125:
126: if (objType == null)
127: {
128: return null;
129: }
130:
131: PropertyInfo pi = objType.GetProperty(InnerExpressions.Find((x) => x.sCnName == strCNName).sEnName);
132:
133: if (pi == null)
134: {
135: return null;
136: }
137: return pi.GetValue(objTarget, index);
138: }
139: /// <summary>
140: /// 获取属性的值
141: /// </summary>
142: /// <param name="strCNName">中文名称</param>
143: /// <param name="objTarget">目标对象,获取该对象下的属性值</param>
144: /// <returns>Value值</returns>
145: public object GetPropertyValueByCNName(string strCNName, object objTarget)
146: {
147: return this.GetPropertyValueByCNName(strCNName, objTarget, null);
148: }
149: /// <summary>
150: /// 类中方法定义的获取
151: /// </summary>
152: /// <param name="strCNName">中文名</param>
153: /// <param name="objTarget">对象</param>
154: /// <param name="param">参数类型</param>
155: /// <returns></returns>
156: public object GetMethodValueByCnName(string strCNName, object objTarget, params object[] param)
157: {
158: Type objType = objTarget.GetType();
159:
160: if (objType == null)
161: {
162: return null;
163: }
164: MemberInfo mi = objType.GetMethod(InnerExpressions.Find((x) => x.sCnName == strCNName).sEnName);
165:
166: if (mi == null)
167: {
168: return null;
169: }
170: return mi;
171: }
172: #endregion
173:
174: #region 内部定义
175: public class ExpressionItem
176: {
177: private string _sCnName;
178:
179: public string sCnName
180: {
181: get { return _sCnName; }
182: set { _sCnName = value; }
183: }
184: private string _sEnName;
185:
186: public string sEnName
187: {
188: get { return _sEnName; }
189: set { _sEnName = value; }
190: }
191: public MemberTypes ItemType;
192: }
193: #endregion
194: }
当每次输入到文本的时候,如果是圆点符号”.”则访问方法,将该输入的文本在创建的字典中查找如果有这个类库,则取出它包含的属性,加入到ListBox中,由ListBox在文本输入区域显示出来。
1: private bool GetItelliInfos(RichTextBox rtb)
2: {
3: int startno = 1;
4: string strName = string.Empty;
5: while (true)
6: {
7: if (rtxtExpression.SelectionStart - startno < 0)
8: {
9: strName = rtxtExpression.Text.Substring(0, startno - 1).Trim();
10:
11: break;
12: }
13: if (rtxtExpression.Text.Substring(rtxtExpression.SelectionStart - startno, 1).ToString().Trim().Equals(string.Empty))
14: {
15: strName = rtxtExpression.Text.Substring(rtxtExpression.SelectionStart - startno, startno).Trim();
16:
17: break;
18: }
19: startno++;
20: }
21: if (strName.Equals(string.Empty))
22: {
23: return false;
24: }
25: FCNExpression f = ListFCN.Find((x) => x.ClassCNName.Equals(strName));
26: if (f == null)
27: {
28: return false;
29: }
30: foreach (var item in f.InnerExpressions)
31: {
32: LstBoxintelli.Items.Add(item.sCnName);
33:
34: }
35: return true;
36: }
总结
我们可以通过Attribute做到很多事情,这次在文中只写出了如果通过Attribute去获取类库的属性名,做出了中英文对应的字典,并在输入点的时候弹出ListBox显示这些属性。下次会写到基于这个功能完成一些基本的判断式和计算式。依然是用中文显示作为输入手段。