使用反射、特性简化代码

    最近老大让我写个验证商品属性的逻辑,我想想不就一项一项判断它为不为空什么的吗?于是乎有了下面的代码

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);

 

是不是简洁了- -

posted @ 2016-01-28 19:13  时噬者  阅读(671)  评论(1编辑  收藏  举报