Quantcast
Viewing all articles
Browse latest Browse all 7

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

If you decide to go the generic way, without applying attributes on your properties, we could build further on Adriano Repetti's answer. My starting point is the IsNullOrEmpty method, which is invoked against any property in the tree of properties of any specified complex object or list of properties of any specified simple object.

The goal is to test against default values and common empty values.

private static bool IsNullOrEmpty(object value){    if (Object.ReferenceEquals(value, null))        return true;    var type = value.GetType();    return type.IsValueType&& Object.Equals(value, Activator.CreateInstance(type));}

By performing not just Object.ReferenceEquals but also ==, we can test both against references as overloaded operators. Nullable<> has an overload that matches == null when HasValue is False. Furthermore, we can check value against the default instance of its type by calling ObjectFactory.CreateInstance. Note that string and DBNull have custom empty values that do not correspond to Activator.CreateInstance.

private static bool IsNullOrEmpty(object value)    {        if (Object.ReferenceEquals(value, null) || value == null)            return true;        // common Empty values        if (value is string && string.IsNullOrEmpty((string)value)) {            return true;        }        if (value is DBNull && (DBNull)value == DBNull.Value) {            return true;        }        var type = value.GetType();        var typeDefault = ObjectFactory.CreateInstance(type);        if (Object.ReferenceEquals(typeDefault, null) || typeDefault == null)            return false;        if (Object.ReferenceEquals(value, typeDefault) || value == typeDefault)            return true;        return false;    }

Appendix: ObjectFactory

ObjectFactory creates the default value of any type. Do not confuse this with the empty value. The latter is context-bound and should be specified on a case-by-case problem. By default, only string.Empty and DBNull.Value are considered empty.

public static class ObjectFactory    {        public static object CreateInstance(Type type)         {            if (TypeSystem.IsNullAssignable(type.NotNull())) {                return null;            }            if (type.IsEnum) {                return Enum.ToObject(type, Convert.ChangeType(0,                      Enum.GetUnderlyingType(type)));            }            if (type.IsValueType) {                return Activator.CreateInstance(type);            }            return null;        }    }

Appendix: TypeSystem

TypeSystem consists of convenience methods for verifying characteristics of a Type. Only the relevant methods are included for brevity.

public static class TypeSystem    {        public static bool IsNullable(Type type)         {            return type.NotNull().IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);        }        public static bool IsNullAssignable(Type type)         {            if (IsNullable(type.NotNull()) || !type.IsValueType) {                return true;            }            if (!type.IsGenericParameter) {                return false;            }            #region Generic Parameter Handling            // probably out-of-scope for this problem            var gpa = type.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;            if (GenericParameterAttributes.None != (gpa & GenericParameterAttributes.ReferenceTypeConstraint)) {                return true;            }            if (GenericParameterAttributes.None != (gpa & GenericParameterAttributes.NotNullableValueTypeConstraint)) {                return false;            }            var gpc = type.GetGenericParameterConstraints();            if (gpc == null || !gpc.Any(x => x.IsClass && IsNullAssignable(x))) {                return false;            }            #endregion            return true;        }    }

Viewing all articles
Browse latest Browse all 7

Trending Articles