0

I have a property that is held in model as a reference to the original component, from my list of components in an application. I've allowed the user to alter this property in a 'working' clone of the object. If they click confirm at the end of the alteration I want to replace the referenced original object directly so that it replaces it in the list that it was original located in.

Is this possible as currently I am simply replacing the relevant properties within the object as it stands.

Example:

Model.OriginalObject = [OriginalComponent];
Model.WorkingObject = [CloneOf][OriginalComponent];

//Interaction performed

Model.WorkingObject.Width = Example.Width;

//Original may not be available if a new component so replace properties only if it is available
if (Model.OriginalObject != null)
{
    Model.OriginalObject = Model.WorkingObject; //This just replaces the reference
}
else
{
    AddComponent(Model.WorkingObject);
}

edit: forgot to say WorkingComponent is a clone of the OriginalComponent

Jack Ward
  • 61
  • 1
  • 7
  • I think you are after a deep copy - see: http://stackoverflow.com/questions/129389/how-do-you-do-a-deep-copy-an-object-in-net-c-specifically ? – Murray Foxcroft May 19 '16 at 09:36
  • are `Model.OriginalObject` and `Model.WorkingObject` using the same reference? what is `[OriginalComponent]`? You cuold replace the properties with reflection or some other techniques. – Sebastian Siemens May 19 '16 at 09:39
  • 1
    I agree with @MurrayFoxcroft, you probably want to have original object and create clone of it for editing. This will allow you to discard changes. Otherwise it's not really clear why you need new object. What will happens with old one? – Sinatr May 19 '16 at 09:40
  • Sorry working component is a clone on the OriginalComponent. Will edit above. – Jack Ward May 23 '16 at 13:24

1 Answers1

1

It all depends on what your object definition is.

For a common object (with only value types and all properties), you can just copy all the public property values. I use this:

private static bool IsValueTypeOrString(Type type)
{
    return type.IsSubclassOf(typeof (ValueType)) || type == typeof(string);
}

public static void ShallowCopyEntity<T>(T source, T dest, params string[] except)
{
    var props = typeof(T).GetProperties(BindingFlags.FlattenHierarchy|BindingFlags.Instance|BindingFlags.Public);
    foreach (var prop in props.Where(x => !except.Contains(x.Name) && IsValueTypeOrString(x.PropertyType)))
    {               
        var getMethod = prop.GetGetMethod(false);
        if(getMethod == null) continue;
        var setMethod = prop.GetSetMethod(false);
        if (setMethod == null) continue;
        prop.SetValue(dest, prop.GetValue(source));
    }
}

PS: I use this to copy scalars from entities in entity framework, hence the "entity" names, but it could work for any object which uses scalars and properties [not fields]

If your object definition is more complicated (contains complex objects and other references), the common way would be implementing ICloneable (or having an specific interface, or just a named method if your class is always the same) which performs the copy, with all the requirements you need for a "clone" (deep copy if needed, etc.). It doesn't need to be generic, it could be made ad-hoc for your specific object type.

Jcl
  • 27,696
  • 5
  • 61
  • 92
  • I'd have to say this is probably the best answer. Currently, as I'm aware of the containing properties I want to change, I'm setting the changes from the working component to the original but thought I'd check to make sure i wasn't missing a really obvious way of doing this. Thanks for your answer will probably come in handy. – Jack Ward May 19 '16 at 15:15