Quantcast
Channel: Generic Null/Empty check for each property of a class - Code Review Stack Exchange
Viewing all articles
Browse latest Browse all 7

Answer by Ron Beyer for Generic Null/Empty check for each property of a class

$
0
0

This is an interesting approach but I would prefer to do this via attributes, for example lets take the following sample class:

public class SampleClass {    public int Property1 { get; set; }    public bool Property2 { get; set; }    public Guid Property3 { get; set; }    public string Property4 { get; set; }    public object Property5 { get; set; }}

Now let's suppose we want to validate this class, but we need to support quite a few types. We don't want to have to modify the validation logic each time we add a new type, so lets create a validation attribute:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]public abstract class ValidatorAttribute : Attribute{    public abstract bool Validate(object value);}

Now we can make specific validation attributes:

public class DefaultValidatorAttribute : ValidatorAttribute{    public override bool Validate(object value)    {        if (value is bool)            return (bool)value != false;        if (value is string)            return !string.IsNullOrWhiteSpace((string)value);        if (value.GetType().IsValueType && value.GetType().IsPrimitive)            return (double)value != 0.0;        return value != null;    }}public class IntValidatorAttribute : ValidatorAttribute{    public override bool Validate(object value)    {        return (int)value <= 0;    }}public class GuidValidatorAttribute : ValidatorAttribute{    public override bool Validate(object value)    {        if (!(value is Guid))            return false;        return ((Guid)value) != Guid.Empty;    }}

And decorate our class:

public class SampleClass{    [IntValidator]    public int Property1 { get; set; }    public bool Property2 { get; set; }    [GuidValidator]    public Guid Property3 { get; set; }    public string Property4 { get; set; }    public object Property5 { get; set; }} 

Now all we need is the validation logic. I think it is acceptable to make an extension method for this:

public static class ValidationExtensions{    public static bool AllPropertiesValid(this object obj)    {        if (obj == null)            return false;        return obj.GetType().GetProperties().All(p =>        {            var attrib = p.GetCustomAttributes(typeof(ValidatorAttribute), true)                                         .FirstOrDefault() as ValidatorAttribute;            if (attrib == null)                attrib = new DefaultValidatorAttribute();            return attrib.Validate(p.GetValue(obj));        });    }}

So, as you can see, this separates concerns, and we can do fun things like this:

public class SkipValidator : ValidatorAttribute{    public override bool Validate(object value)    {        return true;    }}

Which allows us to easily extend without changing the validation logic, now we can skip properties:

public class SampleClass{    [SkipValidator]    public int DoNotCare { get; set; }}

Or if you need special string validators, etc. You can do this without breaking your existing code, invalidating testing, and without introducing a new source of bugs in working code. Additionally, unit testing is a lot cleaner since you can test individual cases against specific attributes.


Viewing all articles
Browse latest Browse all 7

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>