无法映射映射器中的属性

本文关键字:映射 属性 | 更新日期: 2023-09-27 18:26:38

我创建了一个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数据类型时,在源属性中循环时,我得到一个异常。我需要做的是将其放入递归中,并再次映射这些属性。所以我想我错过了一个过滤器检查。

无法映射映射器中的属性

这里有一个非常简单的实现,它将处理复杂的对象属性(显然有一个默认的构造函数):

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就是这样工作的。