-1

I would like to deep copy < MyParameter > par0 into an existing < MyParameter > par1, where some of par1's sub-elements has PropertyChanged event handlers registered, which are not allowed to be overwritten.

I have tested several sources like Automapper, AnyClone, code snippets,.. but couldn't get it work without explicitly list all fields, what I want to avoid. (BinaryFormatter is deprecated, Automappers ForAllOptherMembers was removed,...)

Following example shows the shortened and simplified class-structure. My ShallowCopyFieldsTest() method does only a shallow copy, see also MyButton(), but I would like use a method something like DeepCopyFields(par0, par1). Any help would be great! Thanks.

/Models/Parameter.cs


public partial class MyDouble : ObservableObject
{
    [ObservableProperty]
    private double value;
    [ObservableProperty]
    private double min;
    [ObservableProperty]
    private string info;
}

public class MyGeometry
{
    public MyDouble Diameter { get; set; } = new();
    public MyDouble Lenght { get; set; } = new();

    public MyGeometry()
    {
        Diameter.Value = 10.0;
        Diameter.Min = 0.001;
        Diameter.Info = "Diameter";

        Lenght.Value = 20.0;
        Lenght.Min = 0.001;
        Lenght.Info = "Length";
    }
}

public class MyPhysics
{
    public MyDouble F0 { get; set; } = new();
    public MyDouble F1 { get; set; } = new();

    public MyPhysics()
    {
        F0.Value = 1000.0;
        F0.Min = 0.001;
        F0.Info = "Force0";

        F1.Value = 2000.0;
        F1.Min = 0.001;
        F1.Info = "Force1";
    }
}

public class MyParameter 
{
    public MyDouble XYZ { get; set; } = new();

    public MyGeometry Geometry0 { get; set; } = new();
    public MyGeometry Geometry1 { get; set; } = new();
    public MyPhysics Physics { get; set; } = new();

    public MyParameter()
    {
        XYZ.Value = 1000.0;
        XYZ.Min = 0.001;
        XYZ.Info = "xyz";
    }
}

/ViewModels/MainViewModel.cs

[ObservableProperty]
public MyParameter par0 = new();
[ObservableProperty]
public MyParameter par1 = new();

[RelayCommand]
public void MyButton()
{
    ShallowCopyFieldsTest(par0, par1); 
    ShallowCopyFieldsTest(par0.Geometry0, par1.Geometry0);
    ShallowCopyFieldsTest(par0.Geometry1, par1.Geometry1);
    ShallowCopyFieldsTest(par0.Physics, par1.Physics);
    ShallowCopyFieldsTest(par0.some_deeper_structure...Physics, par1.some_deeper_structure...Physics);

    // TODO: Better solution -->  DeepCopyFields(par0, par1);
}

/Helpers/Helper.cs

public static void ShallowCopyFieldsTest(object _source, object _destin)
{
    foreach (var prop in _source.GetType().GetProperties().ToList())
    {
        try
        { 
            FieldInfo fi;
            fi = typeof(MyDouble).GetField("value", BindingFlags.NonPublic | BindingFlags.Instance);
            fi.SetValue(prop.GetValue(_destin), fi.GetValue(prop.GetValue(_source)));

            fi = typeof(MyDouble).GetField("min", BindingFlags.NonPublic | BindingFlags.Instance);
            fi.SetValue(prop.GetValue(_destin), fi.GetValue(prop.GetValue(_source)));

            fi = typeof(MyDouble).GetField("info", BindingFlags.NonPublic | BindingFlags.Instance);
            fi.SetValue(prop.GetValue(_destin), fi.GetValue(prop.GetValue(_source)));
        }
        catch { }
    }
}
Zulu
  • 1
  • 3

1 Answers1

0
public static void DeepCopyFields(object _source, object _destin)
{
    foreach (var prop in _source.GetType().GetProperties().ToList())
    {
        var d = prop.GetValue(_destin);
        var s = prop.GetValue(_source);

        if (prop.PropertyType.Name != nameof(MyDouble))
        {
            DeepCopyFields(s, d);
        }
        else
        {
            foreach (var p in typeof(MyDouble).GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
            {
                FieldInfo? fi = typeof(MyDouble)?.GetField(p.Name, BindingFlags.NonPublic | BindingFlags.Instance);
                fi?.SetValue(d, fi.GetValue(s));
            }
        }
    }
}
Zulu
  • 1
  • 3
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 26 '23 at 01:29