无法在mapper中映射属性

时间:2015-12-13 08:58:25

标签: c#

我创建了一个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>

1 个答案:

答案 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的工作方式。