我的任务是编写针对现有数据库的例程。这个数据库有几个具有相同结构但名称不同的表(我没有设计这个,请不要建议更改数据库设计)。我在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;
}
无论我尝试什么,我总是得到:
类型&#39; System.Reflection.TargetException&#39;的例外情况发生在mscorlib.dll但未在用户代码中处理。附加信息:对象与目标类型不匹配。
我无法弄清楚我错过了什么。
感谢任何帮助,谢谢!
答案 0 :(得分:1)
您对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()
约束添加到泛型类型参数以要求目标类型具有无参数构造,因此您实际上可以使用表达式new T2()
来创建对象的新实例。