我创建了一个PropertyMapper,它将属性从源映射到目标。
public static void PropertyMap<T, U>(T source, U destination)
where T : class, new()
where U : class, new()
{
List<PropertyInfo> sourceProperties = source.GetType().GetProperties().ToList<PropertyInfo>();
List<PropertyInfo> destinationProperties = destination.GetType().GetProperties().ToList<PropertyInfo>();
foreach (PropertyInfo sourceProperty in sourceProperties)
{
PropertyInfo destinationProperty = destinationProperties.Find(item => item.Name == sourceProperty.Name);
if (destinationProperty != null)
{
try
{
destinationProperty.SetValue(destination, sourceProperty.GetValue(source, null), null);
}
catch (ArgumentException)
{
}
}
}
}
如果我传入包含{int,string,customobject}
的源对象,我可以映射{int and string }
而不是我的'customobject'。当计数器达到customobject
数据类型时循环遍历源属性时,我得到一个异常。我需要做的是将它放在递归中并再次映射这些属性。所以我想我错过了一个过滤器检查。 / p>
答案 0 :(得分:3)
这是一个非常简单的实现,它将处理复杂的对象属性(显然有一个默认的构造函数):
public static void PropertyMap<T, U>(T source, U destination)
where T : class, new()
where U : class, new()
{
List<PropertyInfo> sourceProperties = source.GetType().GetProperties().ToList<PropertyInfo>();
List<PropertyInfo> destinationProperties = destination.GetType().GetProperties().ToList<PropertyInfo>();
PropertyInfo destinationProperty = destinationProperties.Find(item => item.Name == sourceProperty.Name);
if (destinationProperty != null)
{
foreach (PropertyInfo sourceProperty in sourceProperties)
{
if (sourceProperty.PropertyType == destinationProperty.PropertyType &&
simpleTypes.Contains(sourceProperty.PropertyType) &&
simpleTypes.Contains(destinationProperty.PropertyType))
{
// set the value of the simple type directly
destinationProperty.SetValue(destination, sourceProperty.GetValue(source, null), null);
}
else
{
// complex object => we start by instantiating it which will
// of course crash if the target type doesn't have a
// default constructor
var destInstance = Activator.CreateInstance(destinationProperty.PropertyType);
destinationProperty.SetValue(destination, destInstance, null);
// recurse down the object graph
PropertyMap(sourceProperty.GetValue(source, null), destInstance);
}
}
}
}
private static readonly Type[] simpleTypes = new[]
{
typeof(string),
typeof(ushort),
typeof(uint),
typeof(ulong),
typeof(short),
typeof(int),
typeof(long),
typeof(float),
typeof(decimal),
typeof(double),
typeof(DateTime),
typeof(TimeSpan),
// Make sure I didn't forgot some other simple types that you
// would like to handle
};
当然这个解决方案不能处理数组。正如我在评论部分已经指出的那样,对象映射器的完整实现需要更多。我们甚至没有谈论任何表演。使用此代码仅用于一些有趣和学习目的,但从不在生产中,特别是如果您关心性能。在这种情况下,您应该考虑使用Reflection Emit生成动态代码,以便读取和设置不同类型的属性值(您应该缓存),然后直接调用这些动态生成的方法。这就是像Dapper这样的ORM的工作方式。