【问题标题】:Copy class properties from class to a new subclass C#将类属性从类复制到新的子类 C#
【发布时间】:2014-09-01 20:09:31
【问题描述】:

我有一个基类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassPropertyTest
{
    public class BaseClass
    {
        public string name { get; set; }
        public double value { get; set; }
    }
}

然后我有一些从基类派生的类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassPropertyTest
{
    public class ClassA : BaseClass
    {
    }

}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassPropertyTest
{
    public class ClassB : BaseClass
    {
    }

}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassPropertyTest
{
    public class ClassC : BaseClass
    {
    }

}

我还有一个主类,它具有每个类实例的属性。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassPropertyTest
{
    public class MasterClass
    {
        public ClassA ClassA { get; set; }
        public ClassB ClassB { get; set; }
        public ClassC ClassC { get; set; }
    }
}

现在,当我收到主类的实例时,我需要从属性 ClassA 创建一个新类。我使用反射,但我不断收到目标无效的错误。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ClassPropertyTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //Fill master class
            MasterClass o_masterclass = new MasterClass();
            o_masterclass.ClassA = new ClassA { name = "classA", value = 1 };
            o_masterclass.ClassB = new ClassB { name = "classB", value = 2 };
            o_masterclass.ClassC = new ClassC { name = "classc", value = 3 };



            //Now get class by property name
            foreach (PropertyInfo prop in o_masterclass.GetType().GetProperties())
            {
                //Check for class A property
                if (prop.Name == "ClassA") {
                    //Create an instance of that type from ClassA
                    BaseClass instance = (BaseClass)Activator.CreateInstance(prop.PropertyType.BaseType);
                    //Copy properties from masterclass property ClassA to new instance of BaseClass
                    CopyObject<BaseClass>(prop.PropertyType.BaseType, ref instance);
                }
            }
            Console.ReadKey();
        }

        /// <summary>
        /// Copy an object to destination object, only matching fields will be copied
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sourceObject">An object with matching fields of the destination object</param>
        /// <param name="destObject">Destination object, must already be created</param>
        public static void CopyObject<T>(Type sourceObject, ref T destObject)
        {
            //  If either the source, or destination is null, return
            if (sourceObject == null || destObject == null)
                return;

            //  Get the type of each object
            Type sourceType = sourceObject;//.GetType();
            Type targetType = destObject.GetType();

            //  Loop through the source properties
            foreach (PropertyInfo p in sourceType.GetProperties())
            {
                //  Get the matching property in the destination object
                PropertyInfo targetObj = targetType.GetProperty(p.Name);
                //  If there is none, skip
                if (targetObj == null)
                    continue;

                //  Set the value in the destination
                targetObj.SetValue(destObject, p.GetValue(sourceObject, null), null);
            }
        }
    }
}

有人可以帮我吗?谢谢。

@Sergey,我已将 CopyObject 方法更改为:

  public static void CopyObject<T>(T sourceObject, ref T destObject)
        {
            //  If either the source, or destination is null, return
            if (sourceObject == null || destObject == null)
                return;

            //  Get the type of each object
            Type sourceType = sourceObject.GetType();
            Type targetType = destObject.GetType();

            //  Loop through the source properties
            foreach (PropertyInfo p in sourceType.GetProperties())
            {
                //  Get the matching property in the destination object
                PropertyInfo targetObj = targetType.GetProperty(p.Name);
                //  If there is none, skip
                if (targetObj == null)
                    continue;

                //  Set the value in the destination
                targetObj.SetValue(destObject, p.GetValue(sourceObject, null), null);
            }
        }

当我像你告诉我的那样称呼它时,它会起作用。

 CopyObject<BaseClass>(o_masterclass.ClassA, ref instance);

但在我的情况下,o_masterclass.ClassA 实际上是 prop.PropertyType.BaseType。如何将此类型转换为所需的对象?

【问题讨论】:

  • 在 CopyObject 方法中:p.GetValue(sourceObject, null):在这种情况下,sourceObject 是一种类型,而不是该类型的实例...

标签: c# reflection properties


【解决方案1】:

您可以为此使用AutoMapper(或其他映射库):

var otherA = Mapper.Map<ClassA>(o_masterclass.ClassA);

默认情况下,它按名称映射属性。所以在这种情况下你甚至不需要设置任何配置。

在您的解决方案中,您应该传递 sourceObject 而不是它的类型:

public static void CopyObject<T>(T sourceObject, ref T destObject)
{            
    if (sourceObject == null || destObject == null)
        return;

    //  Get the type of each object
    Type sourceType = sourceObject.GetType();
    Type targetType = destObject.GetType();

    //  Loop through the source properties
    foreach (PropertyInfo sourceProp in sourceType.GetProperties())
    {
        //  Get the matching property in the destination object
        PropertyInfo destProp = targetType.GetProperty(sourceProp.Name);
        //  If there is none, skip
        if (destProp == null)
            continue;

        //  Set the value in the destination
        object value = sourceProp.GetValue(sourceObject, null);
        destProp.SetValue(destObject, value, null);
    }
}

这样称呼它:

CopyObject<BaseClass>(o_masterclass.ClassA, ref instance);

还要记住,类型可以包含索引器或只读属性。

【讨论】:

  • 但是为什么它不起作用?我制作了一个控制台应用程序来测试它,在我的情况下,使用不同的类名和属性可以工作。
  • 它在这一行崩溃 // 设置目标中的值 targetObj.SetValue(destObject, p.GetValue(sourceObject, null), null);出现错误:未处理 TargetException
  • @Sergey,Automapper 确实有效,但我需要通过字符串选择需要的属性“ClassA”。这也可以是“ClassB”或“ClassC”。我想成为通用的。
  • @Alex 刚刚验证 - 它确实映射了示例基类的所有属性。你有像我的答案最后一行中指定的一些属性吗?
猜你喜欢
  • 2019-06-07
  • 2014-09-11
  • 1970-01-01
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 2021-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多