Best way to create instance of child object from parent object

前端 未结 7 542
萌比男神i
萌比男神i 2020-12-11 00:04

I\'m creating a child object from a parent object. So the scenario is that I have an object and a child object which adds a distance property for scenarios where I want to s

相关标签:
7条回答
  • 2020-12-11 00:34

    There are libraries to handle this; but if you just want a quick implementation in a few places, I would definitely go for a "copy constructor" as previously suggested.

    One interesting point not mentioned is that if an object is a subclass, then it can access the child's private variables from the within the parent!

    So, on the parent add a CloneIntoChild method. In my example:

    • Order is the parent class
    • OrderSnapshot is the child class
    • _bestPrice is a non-readonly private member on Order. But Order can set it for OrderSnapshot.

    Example:

    public OrderSnapshot CloneIntoChild()
    {
        OrderSnapshot sn = new OrderSnapshot()
        {
            _bestPrice = this._bestPrice,
            _closed = this._closed,
            _opened = this._opened,
            _state = this._state       
        };
        return sn;
    }
    

    NOTE: Readonly member variables MUST be set in the constructor, so you will have to use the child constructor to set these...

    Although I don't like "up-sizing" generally, I use this approach a lot for analytic snapshots...

    0 讨论(0)
  • 2020-12-11 00:36

    You can use reflection to copy properties.

    public class ChildClass : ParentClass
    {
    
    
        public ChildClass(ParentClass ch)
        {
            foreach (var prop in ch.GetType().GetProperties())
            {
                this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(ch, null), null);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-11 00:38

    Seems natural for the base object to have constructor with parameters for its properties:

    public class MyObject 
    {
        public MyObject(prop1, prop2, ...)
        {
            this.Prop1 = prop1;
            this.Prop2 = prop2;
        }
    }
    

    So then, in your descendant object you can have:

    public MyObjectSearch(MyObject obj)
        :base(obj.Prop1, obj.Prop2)
    

    This reduces duplication related to assignments. You could use reflection to automatically copy all properties, but this way seems more readable.

    Note also, that if your classes have so much properties that you're thinking about automatizing of copying of the properties, then they are likely to violate the Single Responsibility Principle, and you should rather consider changing your design.

    0 讨论(0)
  • 2020-12-11 00:40

    The base class needs to define a copy constructor:

    public class MyObject
    {
        protected MyObject(MyObject other)
        {
            this.Prop1=other.Prop1;
            this.Prop2=other.Prop2;
        }
    
        public object Prop1 { get; set; }
        public object Prop2 { get; set; }
    }
    
    public class MyObjectSearch : MyObject
    {
    
        public double Distance { get; set; }
    
        public MyObjectSearch(MyObject obj)
             : base(obj)
        {
            this.Distance=0;
        }
        public MyObjectSearch(MyObjectSearch other)
             : base(other)
        {
            this.Distance=other.Distance;
        }
    }
    

    This way the setting of properties is handled for all derived classes by the base class.

    0 讨论(0)
  • 2020-12-11 00:45

    A generic solution would be to serialize it to json and back. In the json-string is no information about the class name from which it was serialized. Most people do this in javascript.

    As you see it works well for pocco objects but i don't guarantee that it works in every complex case. But it does event for not-inherited classes when the properties are matched.

    using Newtonsoft.Json;
    
    namespace CastParentToChild
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var p = new parent();
                p.a=111;
                var s = JsonConvert.SerializeObject(p);
                var c1 = JsonConvert.DeserializeObject<child1>(s);
                var c2 = JsonConvert.DeserializeObject<child2>(s);
    
                var foreigner = JsonConvert.DeserializeObject<NoFamily>(s);
    
                bool allWorks = p.a == c1.a && p.a == c2.a && p.a == foreigner.a;
                //Your code goes here
                Console.WriteLine("Is convertable: "+allWorks + c2.b);
            }
        }
    
        public class parent{
            public int a;
        }
    
        public class child1 : parent{
         public int b=12345;   
        }
    
        public class child2 : child1{
        }
    
        public class NoFamily{
            public int a;
            public int b = 99999;
        }
    
        // Is not Deserializeable because
        // Error 'NoFamily2' does not contain a definition for 'a' and no extension method 'a' accepting a first argument of type 'NoFamily2' could be found (are you missing a using directive or an assembly reference?)
        public class NoFamily2{
            public int b;
        }
    }
    
    0 讨论(0)
  • 2020-12-11 00:51

    If a shallow copy is enough, you can use the MemberwiseClone method.

    Example:

    MyObject shallowClone = (MyObject)original.MemberwiseClone();
    

    If you need a deep copy, you can serialize/deserialize like this: https://stackoverflow.com/a/78612/1105687

    An example (assuming you write an extension method as suggested in that answer, and you call it DeepClone)

    MyObject deepClone = original.DeepClone();
    
    0 讨论(0)
提交回复
热议问题