-2

I have a translation method, which takes in a class, and 'upgrades' it to a new type. For example:

class Animal {
   public int LegCount {get; set;}
   public string Name {get; set;}
}

class FarmAnimal: Animal {
   public string Benefit {get; set;}
}

// I get passed the Animal type
var a = new Animal();
a.LegCount = 4;
a.Name = "Cow"

// And I need to upgrade it to a Farm Animal
var b = new FarmAnimal();
b.LegCount = a.LegCount;
b.Name = a.Name;
b.Benefit = "Milk";

But if a developer adds a new field to Animal, say EyeCount, they will forget to add the tranlation to the upgrade method.

What I would prefer to do is itterate through the properties of the Animal class, and copy them to the new FarmAnimal class (And then add the extra fields via my own logic). I just need the sub class fields copied.

I was hoping I could so domething like:

        var props = typeof(Animal).GetProperties();
        FarmAnimal target = new FarmAnimal ();
        foreach (var prop in props)
        {
            ....
        }
        target.Benefit = "Milk"; // So, I add the extra fields after translating the sub class fields.

But I am not sure how to do the actual translation. How can I copy each property across within the ForEach. Or is there a better way to achieve this?

Edit: This is very close, I think, but I need to excluse fields that do not have a Set.

        var props = typeof(Animal).GetProperties();
        FarmAnimal fa = new FarmAnimal();
        foreach (var prop in props)
        {
            typeof(FarmAnimal )
                .GetProperty(prop.Name,
                    BindingFlags.IgnoreCase |
                    BindingFlags.Instance |
                    BindingFlags.Public | BindingFlags.SetField)
                
                .SetValue(fa,
                    prop.GetValue(animal));
        }

But I have a few proprties with no Set.

Edit: May have found it.

GetProperties().Where(prop => prop.GetSetMethod() != null)
Craig
  • 18,074
  • 38
  • 147
  • 248
  • Pass the parent into the child I e. `new FarmAnimal(a);` and translate there? – Richard Barker Mar 23 '21 at 01:57
  • Instead of using reflection to solve your issue, have you considered making `Animal` `abstract` with `abstract`/`virtual` properties? – JohanP Mar 23 '21 at 01:59
  • I'm unable to modify Animal at all. So I've gone with creating a new class, extending Animal. @RichardBarker - I'd need to add a translation in the constructor of FormaAnimal in this case? – Craig Mar 23 '21 at 02:06
  • @Craig yes that's what I'm saying. Otherwise look into reflection. – Richard Barker Mar 23 '21 at 02:08
  • If your mapping is simple, you can maybe use something like `Automapper` – JohanP Mar 23 '21 at 02:08
  • @JohanP - Due to the nature of the horrid work I'm on, introducing AutoMapper for this would be like pulling hens teeth. My only avenue at the moment is some form of translation. I like the constructor advice above, but I still need to do the translation. I may have found a way (See edit), but I am crashing with a get property. I need to exclude props where there is no setter. – Craig Mar 23 '21 at 02:10
  • 1
    You can try `var set = typeof(FarmAnimal).GetProperty(prop.Name); if(set?.GetSetMethod() != null) set.SetValue(fa, prop.GetValue(animal));` – JohanP Mar 23 '21 at 02:21

1 Answers1

-1

The answer:

var props = typeof(Animal).GetProperties().Where(prop => prop.GetSetMethod() != null);
        FarmAnimal fa = new FarmAnimal();
        foreach (var prop in props)
        {
            typeof(FarmAnimal )
                .GetProperty(prop.Name,
                    BindingFlags.IgnoreCase |
                    BindingFlags.Instance |
                    BindingFlags.Public | BindingFlags.SetField)
                
                .SetValue(fa,
                    prop.GetValue(animal));
        }
Craig
  • 18,074
  • 38
  • 147
  • 248