使用 C# 反射将一种类型的对象的值复制到另一种类型的对象

Copy values of an object of one type to an object of another using C# reflection

我的任务是针对现有数据库编写例程。这个数据库有几个结构相同,但名称不同的表(我没有设计这个,请不要建议数据库设计更改)。我在 EF 中写这个,模型是数据库优先创建的。

对于这种情况,我能想到的最佳选择是创建一个具有完全相同属性的 class,并创建一个可以接受泛型类型的例程,以将数据从 EF 模型复制到泛型模型。

我的模特:

    // Sample EF database-first created model
    namespace SampleDataModel.Models
    {
        using System;
        using System.Collections.Generic;

        public partial class SampleClassFlavorOne
        {
            public int Id {get; set;}
            public string PropertyOne {get; set;}
            public string Property2 {get; set;}
            public DateTime Property3 {get; set;}
        }
    }

    // Sample of generic class I created
    public class GenericSampleClass{
        public int Id {get; set;}
        public string PropertyOne {get; set;}
        public string Property2 {get; set;}
        public DateTime Property3 {get; set;}
    }

我的日常:

        private static void CopyFlavorToGenericList<T1, T2>(List<T1> fromList, List<T2> toList){
        foreach (var t in fromList)
        {
            //(As you can see, I have tried entering the foreach loop a both ways
            //foreach (var p in typeof(T1).GetProperties())

            foreach (var p in typeof(T2).GetProperties())
            {
                if (p != null && p.CanWrite)
                {
                    dynamic newObject = null;
                    p.SetValue((T2)newObject, p.GetValue(t, null), null);
                }
            }

            toList.Add(toObject);
        }
    }

执行例程:

switch (flavor){
        case "FlavorOne":
            List<SampleClassFlavorOne> _baseFlavor = db.SampleClassFlavorOne.ToList();
            List<GenericSampleClass> _genericFlavor = new List<GenericSampleClass>();

            CopyFlavorToGenericList<SampleClassFlavorOne, GenericSampleClass>(_baseFlavor, _genericFlavor);
            break;
    }

无论我尝试什么,我总是得到:

An exception of type 'System.Reflection.TargetException' occurred in mscorlib.dll but was not handled in user code. Additional information: Object does not match target type.

我不知道我错过了什么。

  1. 我可能遗漏了什么?
  2. 我是不是走错了路?如果是这样,在这些条件下做我想做的事情的正确方法是什么?

感谢任何帮助,谢谢!

您对 GetProperties() 的调用会得到一个 PropertyInfo 对象数组,这些对象 应用于特定类型 。因此,当您调用 GetValue() 时,您正试图从错误类型的对象中获取值。

T2,用来获取PropertyInfo对象的类型是GenericSampleClass,但是你传递给GetValue()方法的对象类型是SampleClassFlavorOne。在你的替代方案中,从 T1 获取属性,你有同样的问题,但是使用 SetValue() 方法,传递(理论上......但不是真的,参见下面的 "Note:")一个对象类型 GenericSampleClass,当 PropertyInfo 对象来自 SampleClassFlavorOne 类型时。

要正确执行此操作,您需要从 类 中获取 PropertyInfo 个对象,并将它们与适当类型的对象一起使用。例如:

private static void CopyFlavorToGenericList<T1, T2>(List<T1> fromList, List<T2> toList) where T2 : new()
{
    var map = from p1 in typeof(T1).GetProperties()
              join p2 in typeof(T2).GetProperties()
                  on p1.Name equals p2.Name
              select new { From = p1, To = p2 };

    foreach (var t in fromList)
    {
        T2 toObject = new T2();

        foreach (var copyItem in map)
        {
            if (copyItem.To.CanWrite)
            {
                copyItem.To.SetValue(toObject, copyItem.From.GetValue(t));
            }
        }

        toList.Add(toObject);
    }
}

注意:您还对创建新对象的方式有疑问。我什至不知道你的意思,像那样使用 dynamic,但它不会起作用。您只是将 null 作为目标对象的值传递,这没有任何用处。

您需要能够根据需要创建目标对象的实例,在泛型方法中实现的方法是将 new() 约束添加到泛型类型参数以要求目标类型具有无参数构造,因此您实际上可以使用表达式 new T2() 创建对象的新实例。