将所有对象参数复制到子类对象的C#方法

3
假设我有一个无法更改的父类对象,比如参数很多的 ListBox 实例。现在我创建了一个子类:
class PlaylistBox : ListBox
{

    void CopySettingsFrom(ListBox In)
    {
         //...what now?
    }
}

问题 - 如何有效地从In对象向PlaylistBox的新对象进行浅复制?


5
如果Listbox实现了ICloneable,你就调用Clone。否则你需要编写代码。这并没有什么神奇的地方。 - Panagiotis Kanavos
取决于您是否需要基类的公共属性和字段,还是内部或私有成员。基本上,您只需为要复制的每个字段/属性编写this.MyProperty = In.MyProperty即可。如果有很多字段/属性,反射可能会有所帮助。 - MakePeaceGreatAgain
@PanagiotisKanavos 在构造函数中调用 Clone 并不会有太大帮助,因为它只是返回一个实例,显然不能分配给 this。你需要将克隆的成员复制到新实例中。 - MakePeaceGreatAgain
是的,我不想逐个编写它们 :) - Ch3shire
1
你必须指明你想要复制哪些成员。 - MakePeaceGreatAgain
显示剩余4条评论
2个回答

2
您可以使用反射技术。
//Other Imports...
using System.Reflection;

public PlaylistBox(ListBox In)
{
    PropertyInfo[] properties = typeof(ListBox).GetProperties();

    foreach (PropertyInfo p in properties)
        if (p.CanRead && p.CanWrite)
            p.SetMethod.Invoke(this, new object[] { p.GetMethod.Invoke(In, null) });
}

对于 .NET < 4.5 版本,将 GetMethodSetMethod 属性的调用替换为分别调用 GetGetMethod()GetSetMethod() 方法。


2

以下是三种基于反射和AutoMapper的示例方法,附有说明:

internal class Program
    {
        private static void Main(string[] args)
        {
            Example1();
            Example2();
            Example3();
        }

        public static void Example1()
        {
            Console.WriteLine("This example shows using copy with reflection. Minus of this method - u have to implement FULL copy for each class or u will copy only references to object properties");

            //creating new parent class with some values
            var parentClass = new ParentClass
            {
                Property1 = "qqq",
                Property2 = 1,
                ObjectProperty = new SomeClassWithObjectProperty
                {
                    ObjectProperty = new SomeObjectClass {SomeProperty = "www"}
                }
            };

            //crating new child class and copy REFERENCES to properties
            var childClassReflection = new ChildClassReflection(parentClass);

            //changing properties of parent
            parentClass.Property1 = "rrr";
            parentClass.Property2 = 2;
            parentClass.ObjectProperty.ObjectProperty.SomeProperty = "eee";

            //we will get OLD values for VALUE types and OLD values for REFERENCE types
            //qqq 1 WWW
            Console.WriteLine(childClassReflection.Property1 + " " + childClassReflection.Property2 + " " + childClassReflection.ObjectProperty.ObjectProperty.SomeProperty);
        }

        public static void Example2()
        {
            Console.WriteLine();
            Console.WriteLine("This example shows using copy with reflection WITH FULL COPY");

            //creating new parent class with some values
            var parentClass = new ParentClass
            {
                Property1 = "qqq",
                Property2 = 1,
                ObjectProperty = new SomeClassWithObjectProperty
                {
                    ObjectProperty = new SomeObjectClass {SomeProperty = "www"}
                }
            };

            //crating new child class and copy REFERENCES to properties
            var childClassReflection = new ChildClassReflectionWithFullCopy(parentClass);

            //changing properties of parent
            parentClass.Property1 = "rrr";
            parentClass.Property2 = 2;
            parentClass.ObjectProperty.ObjectProperty.SomeProperty = "eee";

            //we will get OLD values for VALUE types and NEW values for REFERENCE types
            //qqq 1 eee
            Console.WriteLine(childClassReflection.Property1 + " " + childClassReflection.Property2 + " " + childClassReflection.ObjectProperty.ObjectProperty.SomeProperty);
        }

        public static void Example3()
        {
            //here i will show copy using AutoMapper
            Console.WriteLine();
            Console.WriteLine("This example shows using copy with AutoMapper");

            //creating new parent class with some values
            var parentClass = new ParentClass
            {
                Property1 = "qqq",
                Property2 = 1,
                ObjectProperty = new SomeClassWithObjectProperty
                {
                    ObjectProperty = new SomeObjectClass { SomeProperty = "www" }
                }
            };

            Mapper.Initialize(cfg => cfg.CreateMap<ParentClass, ChildClassAutoMapper>());           

            //crating new child class and copy REFERENCES to properties
            var childClassReflection = Mapper.Map<ChildClassAutoMapper>(parentClass);

            //changing properties of parent
            parentClass.Property1 = "rrr";
            parentClass.Property2 = 2;
            parentClass.ObjectProperty.ObjectProperty.SomeProperty = "eee";

            //we will get OLD values for VALUE types and OLD values for REFERENCE types
            //qqq 1 eee
            Console.WriteLine(childClassReflection.Property1 + " " + childClassReflection.Property2 + " " + childClassReflection.ObjectProperty.ObjectProperty.SomeProperty);
        }
    }

    public class ChildClassAutoMapper:ParentClass
    {       
    }

    public class ChildClassReflection : ParentClass
    {
        public ChildClassReflection(ParentClass parentClass)
        {
            foreach (var p in ParentProperties)
                p.SetMethod.Invoke(this, new[] {p.GetMethod.Invoke(parentClass, null)});
        }

        //do it only once for best performance
        private static PropertyInfo[] ParentProperties { get; } = typeof(ParentClass).GetProperties().Where(c => c.CanRead && c.CanWrite).ToArray();
    }

    public class ChildClassReflectionWithFullCopy : ParentClass
    {
        public ChildClassReflectionWithFullCopy(ParentClass parentClass)
        {
            var parentClassLocal = JsonConvert.DeserializeObject<ParentClass>(JsonConvert.SerializeObject(parentClass));
            foreach (var p in ParentProperties)
                p.SetMethod.Invoke(this, new[] {p.GetMethod.Invoke(parentClassLocal, null)});
        }

        //do it only once for best performance
        private static PropertyInfo[] ParentProperties { get; } = typeof(ParentClass).GetProperties().Where(c => c.CanRead && c.CanWrite).ToArray();
    }

    public class ParentClass
    {
        public string Property1 { get; set; }
        public int Property2 { get; set; }
        public SomeClassWithObjectProperty ObjectProperty { get; set; }
    }

    public class SomeClassWithObjectProperty
    {
        public SomeObjectClass ObjectProperty { get; set; }
    }

    public class SomeObjectClass
    {
        public string SomeProperty { get; set; }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接