jeudi 17 septembre 2015

How to find out if a property value has been set to the default value for it's type in C#

I have a model ... several actually but we only need one for the sake of the question ...

public class DeliverableType : BModelBase, ISingleID
{

    public Int64 ID { get; set; }

    public String Label { get; set; }

    public String Description { get; set; }

    public Int64 TestID { get; set; }

}

So given this model I would like to be able to run a method such as ...

DeliverableType objA = new DeliverableType();
DeliverableType objB = Repository.GetDeliverableType(objA.ID);

objA.Merge(objB);

This would compare the property values of objA against the corresponding properties of objB. Any property value on objA that was assigned the default value (based on its type) should be replaced by the value assigned to the corresponding property on objB.

So if objA values were set to ...

objA.ID          = 100;
objA.Label       = null;  // equals default(String)
objA.Description = "Some clever description here";
objA.TestID      = 0;     // equals default(Int64)

And objB values were set to ...

objA.ID          = 100;
objA.Label       = "Clever TITLE";
objA.Description = "Some not-so clever description here";
objA.TestID      = 50;    

I would want to run ...

objA.Merge(objB);

And the resulting objA property values would look like ...

objA.ID          = 100;
objA.Label       = "Clever TITLE";
objA.Description = "Some clever description here";
objA.TestID      = 50;

All the fields on objA that had been assigned default values would have been replaced with values from objB.

I have looked around and found bits and pieces of advice concerning iterating through properties, or finding the type of properties but when putting these pieces together it's not working.

I am creating an extension class so that it will just be tacked on the the appropriate models. I identify which models to tack the extension to based on the base class that they will all derive from.

    public static void Merge(this BModelBase model, BModelBase entity)
    {
        IList diffProperties = new ArrayList();
        foreach (var modelProp in model.GetType().GetProperties())
        {
            var propType        = modelProp.PropertyType;
            var entityPropVal   = entity.GetType().GetProperty(modelProp.Name).GetValue(entity);
            var modelPropVal    = modelProp.GetValue(model);

            if (!Object.Equals(modelPropVal, entityPropVal) )
            {
                if (propType.IsValueType && modelPropVal == default(propType))  // compiler chokes on this line
                {
                    modelProp.SetValue(model, entityPropVal);
                }
            }
        }
    }

To be fair I did not really expect this exact code to work but expected that it would lead me in the right direction. However, I am getting a weird error. On the line ...

if (propType.IsValueType && modelPropVal == default(propType))

the SECOND occurrence of the variable "propType" in the default() call is returning the compiler error ...

The type or namespace name 'propType' could not be found (are you missing a using directive or an assembly reference?)

Which makes no sense because it's clearly it's been defined and is actually being recognized elsewhere in the code, even in the same expression.

Looking for any thoughts on why the compiler is barfing on this line plus any thoughts on how this functionality could be better implemented. If a new direction by-passes my compiler issue ... I'm good with that too.

thanks





Aucun commentaire:

Enregistrer un commentaire