Copying the contents of a base class from a derived class

后端 未结 10 1439
粉色の甜心
粉色の甜心 2021-01-01 17:19

I currently have a derived class and a base class. How can I make the base class of the derived class equal to a base class that I have? Will a shallow copy work?



        
相关标签:
10条回答
  • 2021-01-01 17:30

    Based on mnyarar code, it would be necessary update the way to obtain the properties:

    public static T Map<T, TU>(this T target, TU source)
    {
    
    
        // list of writable properties of the destination
        List<PropertyInfo> tprops = typeof(T).GetTypeInfo().DeclaredProperties
                                            .Where(x => x.CanWrite == true).ToList();
    
        tprops.ForEach(prop =>
                {
                    // check whether source object has the the property
                    var sp = source.GetType().GetProperty(prop.Name);
                    if (sp != null)
                    {
                        // if yes, copy the value to the matching property
                        var value = sp.GetValue(source, null);
                        target.GetType().GetProperty(prop.Name).SetValue(target, value, null);
                    }
                });
    }
    
    0 讨论(0)
  • 2021-01-01 17:39

    Just change this.

    Derived d = (Derived)b;
    

    Also, your name data type should be string, not int

    0 讨论(0)
  • 2021-01-01 17:41

    You can always use Object.MemberwiseClone to copy it.

    http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx

    Or implement the IClonable interface: http://msdn.microsoft.com/en-us/library/system.icloneable.aspx

    0 讨论(0)
  • I found EMIT may help you for this.

    For we will spend too long in reflection but we can be fast in Emit.

      private static void CloneObjectWithIL<T>(T source, T los)
        {
            var dynamicMethod = new DynamicMethod("Clone", null, new[] { typeof(T), typeof(T) });
            ILGenerator generator = dynamicMethod.GetILGenerator();
    
            foreach (var temp in typeof(T).GetProperties().Where(temp=>temp.CanRead&&temp.CanWrite))
            {
                generator.Emit(OpCodes.Ldarg_1);// los
                generator.Emit(OpCodes.Ldarg_0);// s
                generator.Emit(OpCodes.Callvirt,temp.GetMethod);
                generator.Emit(OpCodes.Callvirt, temp.SetMethod);
            }
            generator.Emit(OpCodes.Ret);
            var clone = (Action<T, T>) dynamicMethod.CreateDelegate(typeof(Action<T, T>));
            clone(source, los);
        }
    

    It can be use as this code:

    public class Base
    {
        public string BaseField;
    }
    
    public class Derived : Base
    {
        public string DerivedField;
    }
    
    Base base = new Base();
    //some alother code
    Derived derived = new Derived();
    CloneObjectWithIL(base, derived);
    

    The more fast code is to cache it.

        // ReSharper disable once InconsistentNaming
        public static void CloneObjectWithIL<T>(T source, T los)
        {
            //See http://lindexi.oschina.io/lindexi/post/C-%E4%BD%BF%E7%94%A8Emit%E6%B7%B1%E5%85%8B%E9%9A%86/
            if (CachedIl.ContainsKey(typeof(T)))
            {
                ((Action<T, T>) CachedIl[typeof(T)])(source, los);
                return;
            }
            var dynamicMethod = new DynamicMethod("Clone", null, new[] { typeof(T), typeof(T) });
            ILGenerator generator = dynamicMethod.GetILGenerator();
    
            foreach (var temp in typeof(T).GetProperties().Where(temp => temp.CanRead && temp.CanWrite))
            {
                if (temp.GetAccessors(true)[0].IsStatic)
                {
                    continue;
                }
    
                generator.Emit(OpCodes.Ldarg_1);// los
                generator.Emit(OpCodes.Ldarg_0);// s
                generator.Emit(OpCodes.Callvirt, temp.GetMethod);
                generator.Emit(OpCodes.Callvirt, temp.SetMethod);
            }
            generator.Emit(OpCodes.Ret);
            var clone = (Action<T, T>) dynamicMethod.CreateDelegate(typeof(Action<T, T>));
            CachedIl[typeof(T)] = clone;
            clone(source, los);
        }
    
        private static Dictionary<Type, Delegate> CachedIl { set; get; } = new Dictionary<Type, Delegate>();
    
    0 讨论(0)
  • 2021-01-01 17:46

    I came up with a pretty good pattern for dealing with this situation.

    public class Base
    {
        public int BaseField;
    
        /// <summary>
        /// Apply the state of the passed object to this object.       
        /// </summary>
        public virtual void ApplyState(Base obj)
        {
            BaseField = obj.BaseField;
        }
    }
    
    public class Derived : Base
    {
        public int DerivedField;
    
        public override void ApplyState(Base obj)
        {
            var src = srcObj as Derived;
    
            if (src != null)
            {
                DerivedField = src.DerivedField;
            }
    
            base.ApplyState(srcObj);        
        }
    }
    

    Given any two objects that share type 'Base', you can apply A to B or B to A.

    0 讨论(0)
  • 2021-01-01 17:47

    Another approach would be to map the base class to derived class:

    /// <summary>
    /// Maps the source object to target object.
    /// </summary>
    /// <typeparam name="T">Type of target object.</typeparam>
    /// <typeparam name="TU">Type of source object.</typeparam>
    /// <param name="target">Target object.</param>
    /// <param name="source">Source object.</param>
    /// <returns>Updated target object.</returns>
    public static T Map<T, TU>(this T target, TU source)
    {
        // get property list of the target object.
        // this is a reflection extension which simply gets properties (CanWrite = true).
        var tprops = target.GetProperties();
    
        tprops.Where(x=>x.CanWrite == true).ToList().ForEach(prop =>
        {
            // check whether source object has the the property
            var sp = source.GetType().GetProperty(prop);
            if (sp != null)
            {
                // if yes, copy the value to the matching property
                var value = sp.GetValue(source, null);
                target.GetType().GetProperty(prop).SetValue(target, value, null);
            }
        });
    
        return target;
    }
    

    Example:

    var derivedClass = new DerivedClass();
    derivedClass.Map(baseClass);
    
    0 讨论(0)
提交回复
热议问题