[原创]通过Attribute完成中文智能提示
2009-07-29 14:10 水随风 阅读(358) 评论(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显示这些属性。下次会写到基于这个功能完成一些基本的判断式和计算式。依然是用中文显示作为输入手段。
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号