i want to make some validations in a class, so i thought I could use attributes. Like this:
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
}
}
But I know that I can't do it, because this is not how attributes work. And, if there is a way, it would use some kind of heavy reflection and kludges that I want to avoid.
The validation I want to do is like this:
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; }
}
But I want to do it faster, without all this code. I want as fast as using an Attribute.
There is a way i could do it?
Normally you would not do stuff like this with an attribute, but it is possible, although not recommendable. Use at your own risk :) (you will let loose hell if the property is not decorated with the 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);
}
}
EDIT I've extended the example. Still a horrible solution, but it works.