asp.net MVC 特性(Attributes)的简单应用--属性特性

属性特性主要应用于类的字段或者属性,以验证是否符合特性。

asp.net MVC里就自带了许多这样的属性特性,例如[Required]、[Display(Name = "用户名")]、[DataType(DataType.Password)]、

[StringLength(100, ErrorMessage = "{0} 必须至少包含 {2} 个字符。", MinimumLength = 6)]等等

它们都是继承了ValidationAttribute这个类,主要用于web前端的自动验证。

不过,今天我要学习的并不是继承ValidationAttribute的属性特性(改天学习了再记上),而是学习服务端的属性特性,用于在服务端验证类的属性特性。

首先创建一个MyStringLenthAttribute类,它继承Attribute(自定义属性的基类)

    /// <summary>
    /// 属性的长度特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Field|AttributeTargets.Property)]
    public sealed class MyStringLenthAttribute:Attribute
    {
        public MyStringLenthAttribute(string displayName, int maxLength)
        {
            this.DisplayName = displayName;
            this.MaxLength = maxLength;
        }
        //显示的名称,对外是只读的,所以不能通过可选参数来赋值,必须在构造函数中对其初始化。
        public string DisplayName { get; private set; }
        //长度最大值,对外是只读的,所以不能通过可选参数来赋值,必须在构造函数中对其初始化。
        public int MaxLength { get; private set; }
        public string ErrorMessage { get; set; }
        public int MinLength { get; set; }
    }

就这么简单,一个可以验证属性长度的attribute就建立起来了,然后要给它赋予实现的方法(核心)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Reflection;
using MvcApplication1.Models;
using System.Linq.Expressions;
using System.Text;

namespace MvcApplication1.Filter
{
    public class MyStringLenthValid
    {
        /// <summary>
        /// 属性的长度验证,属性名列表和属性的长度要一一对应
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="classProperties">实体类的属性名列表</param>
        /// <param name="len">实体类的属性的长度</param>
        /// <returns></returns>
        public static bool IsValid<T>(ClassProperty[] classProperties,int[] len)
        {
            StringBuilder isValidateFlag=new StringBuilder();
            for (int i = 0; i < classProperties.Length; i++)
            {
                if (string.IsNullOrWhiteSpace(classProperties[i].PropertyName)) return false;
                //获取实体类T的公共属性
                PropertyInfo p = typeof(T).GetProperty(classProperties[i].PropertyName);
                //获取此成员的自定义特性的数组
                foreach (var attribute in p.GetCustomAttributes(true))
                {
                    //如果特性属于MyStringLenthAttribute
                    if (attribute is MyStringLenthAttribute) { 
                        //把该特性强制转换成MyStringLenthAttribute
                        MyStringLenthAttribute attr = (MyStringLenthAttribute)attribute;
                        string displayName = attr.DisplayName;
                        int maxLength = attr.MaxLength;
                        int minLength = attr.MinLength;
                        string msg = attr.ErrorMessage;
                        if (len[i] < minLength || len[i] > maxLength)
                        {
                            Console.WriteLine(msg, displayName, minLength, maxLength);
                            isValidateFlag.Append("false");
                        }
                        else
                        {
                            isValidateFlag.Append("true");
                        }
                        break;
                    }
                }
            }
            //if(isValidateFlag.ToString().Contains("false")){
            //    return false;
            //}
            //else
            //    return true;
            return isValidateFlag.ToString().Contains("false") ? false : true;
        }
    }
        
}

 

从上面方法参数ClassProperty[] classProperties,ClassProperty是一个只定义了 实体类属性名的类,主要用于保存需要动态地验证类的属性

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication1.Models
{
    public class ClassProperty
    {
        /// <summary>
        /// 属性名
        /// </summary>
        public string PropertyName { get; set; }

        public ClassProperty(string propertyName)
        {
            this.PropertyName = propertyName;
        }
    }
}

好的。万事俱备了。最后就来一个测试的实体类Order,其中OrderId和Count都用了MyStringLenthAttribute这个特性

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

//using System.ComponentModel.DataAnnotations;
//using System.ComponentModel.DataAnnotations.Schema;
using MvcApplication1.Filter;

namespace MvcApplication1.Models
{
    public class Order
    {
        public string OrderName { get; set; }

        [MyStringLenth("订单号", 6, MinLength = 3, ErrorMessage = "{0}的长度介于{1}和{2}之间,请重新输入!")]
        public string OrderId { get; set; }

        [MyStringLenth("数量", 3, MinLength = 1, ErrorMessage = "{0}的长度介于{1}和{2}之间,请重新输入!")]
        public string Count { get; set; }
        public int Number { get; set; }
    }
}

最后实现验证(上面的代码我都写在了MVC上,下面的是另建的一个控制台,引用MVC的dll)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using MvcApplication1.Models;
using MvcApplication1.Filter;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input = string.Empty;
            string count = string.Empty;
            Order order;
            int[] lengths;
            ClassProperty[] cps = new ClassProperty[] { new ClassProperty("OrderId"), new ClassProperty("Count") };
            do
            {
                Console.WriteLine("请输入订单号:");
                input = Console.ReadLine();
                Console.WriteLine("请输入数量:");
                count = Console.ReadLine();
                order = new Order { OrderId = input, Count = count };
                lengths = new int[] { order.OrderId.Length, order.Count.Length };//要和cps一一对应
            }
            while (!MyStringLenthValid.IsValid<Order>(cps, lengths));
            Console.WriteLine("订单号输入正确,按任意键退出!");
            Console.ReadKey();
        }
    }
}

运行结果

 

posted @ 2017-01-26 02:02  花生打代码会头痛  阅读(685)  评论(0)    收藏  举报