我想在课堂上进行一些验证,所以我想我可以使用属性。 像这样:
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; }
}
但是我想更快地完成它,没有所有这些代码。我希望和使用属性一样快。
有一种方法可以做到吗?
答案 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);
}
}
编辑我已经扩展了这个例子。仍然是一个可怕的解决方案,但它的确有效。