Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用C反射将一种类型的对象的值复制到另一种类型的对象_C#_Entity Framework_Reflection_Setvalue - Fatal编程技术网

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

C# 使用C反射将一种类型的对象的值复制到另一种类型的对象,c#,entity-framework,reflection,setvalue,C#,Entity Framework,Reflection,Setvalue,我的任务是针对现有数据库编写一个例程。这个数据库有几个表具有相同的结构,但不同的名称我没有设计这个,请不要建议更改数据库设计。我在EF中写这篇文章,模型是首先在数据库中创建的 对于这种情况,我能想到的最佳选择是创建一个具有完全相同属性的类,并创建一个可以接受泛型类型的例程,以将数据从EF模型复制到泛型模型 我的模型: // Sample EF database-first created model namespace SampleDataModel.Models {

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

对于这种情况,我能想到的最佳选择是创建一个具有完全相同属性的类,并创建一个可以接受泛型类型的例程,以将数据从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;
    }
无论我尝试什么,我总是得到:

mscorlib.dll中发生“System.Reflection.TargetException”类型的异常,但未在用户代码中处理。其他信息:对象与目标类型不匹配

我不知道我错过了什么

我会错过什么? 我走错方向了吗?如果是这样,在这些条件下,我想做的事情的正确方法是什么? 感谢您的帮助,谢谢

对GetProperties的调用将获取应用于该特定类型的PropertyInfo对象数组。因此,当您调用GetValue时,您试图从错误类型的对象获取值

也就是说,T2,用于获取PropertyInfo对象的类型,是GenericSampleClass,但是传递给GetValue方法的对象的类型是SampleClassFlavorOne。在您的替代方案中,从T1获取属性,您也有同样的问题,但是使用SetValue方法,在理论上传递…但不是真的,请参见注释:下面是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 T2来创建对象的新实例。

谢谢您,彼得!特别是,感谢您不仅提供了代码,而且还提供了出色的解释!我完全理解我遇到的问题,以及我的决心。我必须在你的字条上为自己辩护一点;这是我在这个网站上看到的尝试一些解决方案的最后努力的一部分——我想知道我自己该怎么做。我不知道如何使t2toobject=newt2;工作,你的建议添加T2:new是完美的!再次感谢+还有一个关于这个问题的问题:我知道反射本身就是一种性能上的冲击。创建变量映射的需要是否会增加对性能的影响?看看这个解决方案,我几乎想说我只使用了一次反射,而不是在我的fromList的每个对象上,因此实际上减少了这个命中率。我说的对吗?@Matt:是的,创建一次地图对象比为列表中的每个对象创建一次要好。调用GetValue和SetValue方法仍有成本,这比直接访问属性要慢。与其他技术相比,反射速度较慢,但这可能是问题,也可能不是问题,这取决于您需要执行此代码的频率。如果速度成了一个问题,您可以通过构建表达式对象来访问可以编译的属性,并使用字典在对复制方法的调用中缓存这些属性来改善问题。