获取属性修饰属性的值

时间:2012-11-06 12:51:52

标签: c# validation maxlength

我想在课堂上进行一些验证,所以我想我可以使用属性。 像这样:

public class someClass
{
    [Lenght(200)]
    public string someStr { get; set; }
}
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
sealed class Lenght  : Attribute
{
    public Lenght(int Lenght)
    {
         //some code   
    }
}

但我知道我不能这样做,因为这不是属性的工作方式。并且,如果有办法,它会使用我想要避免的某种重反射和kludges。

我想要做的验证是这样的:

public class someClass
{

    public string someStr
    {
        get
        {
            return _someStr;
        }
        set
        {
            if (value.Length > 200)
            {
                throw new Exception("Max Length is 200!");
            }
            else _someStr = value;
        }
    }
    private string _someStr { get; set; }
}

但是我想更快地完成它,没有所有这些代码。我希望和使用属性一样快。

有一种方法可以做到吗?

3 个答案:

答案 0 :(得分:1)

属性的目的是将关于程序集,类型,成员,参数等的元数据声明到其他组件,工具,编译器等。当然,你可以做你想要的,但这将涉及反映在你的第二个例子中,你可以通过自己来确定价值。

您应该考虑的是一个验证框架,其中包含所有这些内容,并允许您单独和外部验证。

有许多验证框架可供选择。我最喜欢的两个流行的是FluentValidation和企业图书馆的Validation Application Block

另一方面,也许你只是在寻找一个好的Guard班级或Code Contracts。这些用于与验证不同的目的(参见Design by Contract)。你可以想象将属性(我建议重用Data Annotations)与一些面向方面的编程相结合,以便以声明方式为你完成保护(参见PostSharp)。然而,这可能只是炫耀:)。

答案 1 :(得分:1)

您可以创建一个将该字段作为ref参数的方法:

public static void SetWithMaxLength(ref string field, string value, int maxLength)
{
    if(value.Length > maxLength) throw new Exception("Max length is " + maxLength);
    field = value;
}

然后你可以把你的二传手写为:

set
{
    SetWithMaxLength(ref this._someStr, value, 200);
}

答案 2 :(得分:1)

通常你不会用属性做这样的事情,但它是可能的,虽然不值得推荐。使用风险自负:)(如果财产没有用LengthAttribute装饰,你会放松地狱:))

    public interface AttributeValidator
    {
        void CheckOk(object value);
    }

    public class LenghtAttribute : Attribute, AttributeValidator
    {
        public int MaxLength { get; private set; }
        public LenghtAttribute(int lenght)
        {
            this.MaxLength = lenght;
        }

        public void CheckOk(object value)
        {
            var str = value as string;
            if (str != value)
                throw new Exception("Not a string!");

            if (str != null && str.Length > MaxLength)
                throw new Exception("To long!");
        }
    }

    public class DoesNotContain : Attribute, AttributeValidator
    {
        public string Chars { get; private set; }
        public DoesNotContain(string chars)
        {
            this.Chars = chars;
        }

        public void CheckOk(object value)
        {
            var str = value as string;
            if (str != value)
                throw new Exception("Not a string!");

            if (str != null && Chars.Any(c => str.Contains(c)))
                throw new Exception("Contains forbidden character!");
        }
    }

    public class SomeClass
    {
        private string _someString;

        [Lenght(200)]
        [DoesNotContain("$#2")]
        public string SomeString
        {
            get { return _someString; }
            set
            {
                Utils.Validate("SomeString", this, value);
                _someString = value;
            }
        }
    }

    public static class Utils
    {
        public static void Validate(string property, object instance, string value)
        {
            var validators = instance.GetType().GetProperty(property)
                .GetCustomAttributes(false).OfType<AttributeValidator>();

            foreach (var validator in validators)
                validator.CheckOk(value);
        }
    }

编辑我已经扩展了这个例子。仍然是一个可怕的解决方案,但它的确有效。