使用反射、特性简化代码
最近老大让我写个验证商品属性的逻辑,我想想不就一项一项判断它为不为空什么的吗?于是乎有了下面的代码
private StringBuilder validateMessage = new StringBuilder(); public void ValidateItem(Item item) { if(string.IsNullOrEmpty(item.Name)) { validateMessage .Append("商品名称为必填项"); } if(string.IsNullOrEmpty(item.品牌)) { validateMessage .Append("商品品牌为必填项"); } if(item.price<=0) { validateMessage .Append("商品价格为必填大于0"); } ...... 几百行 // 写到这里发现不对啊,商品必填项有20多个,难道我要一直这样写吗! }
然后要验证的不止只有这种商品啊!还有其他B商品,C商品,别说必填项,属性都差别很大,T_T而且这样子看上去好恶心啊,突然想起其实判断的代码都差不多嘛- -能不能用点反射什么的简化下,
对啊,反射出属性然后遍历验证不就行了......但是还有个问题,那岂不是所有属性都要判断,我只是想判断必填属性而已,我怎么知道哪些属性是必填的,哪些属性是非必填啊?突然又想起了属性上面经常带个特性如[serviable]等,相当于一个标记,对了,我自己定义一个标记不就行了~(这是我第一次用自定义标记,纪念下哈哈),于是有了下面这段代码。
//其实标记就是一个类 public sealed class RequireAttribute : Attribute //所有标记都要继承Attribute { public RequireAttribute(bool isRequire) { this._isRequire = isRequire; } private bool _isRequire; public bool IsRequire { get { return _isRequire; } } }
然后我在必填属性上这样加:
public class Item { [Require(true)] //这里其实就是调用了上面特性的构造函数RequireAttribute(bool isRequire),主要Require和RequireAttribute是等价的,相当于Login和LoginController一样。 public string Name{get;set;} }
有些人就说加了有毛用啊,当然有用啦!当反射反射属性时,也可以反射出这个特性!知道为什么叫特性了吧,因为是给这个属性额外添加的性质(个人理解- -)
private void CheckIsRequired<T>(T instance) { Type t = typeof(T); PropertyInfo[] props = t.GetProperties(); //获取所有属性 foreach (PropertyInfo prop in props) //遍历属性 { RequireAttribute Attr = (RequireAttribute)Attribute.GetCustomAttribute(prop, typeof(RequireAttribute)); //注意,这里就是获取某个属性的特性 if (Attr == null) { continue; } object obj = prop.GetValue(instance, null); //获取到对象相应的属性值 string propertyType = prop.PropertyType.ToString().ToLower(); if (propertyType.Contains("string")) { if (obj == null && Attr.IsRequire) { //记录必填的字符串 ValidatorMessage.Append(prop.Name).Append("为必填项").Append(","); } } else if (propertyType.Contains("int")) { if ((int)obj == 0 && Attr.IsRequire) { //记录必填的数值型 ValidatorMessage.Append(prop.Name).Append("不能为0").Append(","); } } } }
然后调用的时候这样调用
CheckIsRequired<ItemA>(itemA);
CheckIsRequired<ItemB>(itemB);
是不是简洁了- -