使用隐式转换在运行时进行转换

时间:2012-03-28 16:39:32

标签: c#-4.0 casting

我有以下代码,它通过匹配属性名称将属性值从一个对象复制到另一个对象:

public static void CopyProperties(object source, object target,bool caseSenstive=true)
    {
        PropertyInfo[] targetProperties = target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
        PropertyInfo[] sourceProperties = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (PropertyInfo tp in targetProperties)
        {
            var sourceProperty = sourceProperties.FirstOrDefault(p => p.Name == tp.Name);
            if (sourceProperty == null && !caseSenstive)
            {
                sourceProperty = sourceProperties.FirstOrDefault(p => p.Name.ToUpper() == tp.Name.ToUpper());
            }
            // If source doesn't have this property, go for next one.
            if(sourceProperty ==null)
            {
                continue;
            }

            // If target property is not writable then we can not set it; 
            // If source property is not readable then cannot check it's value 
            if (!tp.CanWrite || !sourceProperty.CanRead)
            {
                continue;
            }

            MethodInfo mget = sourceProperty.GetGetMethod(false);
            MethodInfo mset = tp.GetSetMethod(false);

            // Get and set methods have to be public 
            if (mget == null)
            {
                continue;
            }

            if (mset == null)
            {
                continue;
            }


            var sourcevalue = sourceProperty.GetValue(source, null);
            tp.SetValue(target, sourcevalue, null);

        }
    }

当目标和源上的属性类型相同时,这种方法很有效。但是当需要进行强制转换时,代码不起作用。

例如,我有以下对象:

class MyDateTime
{
    public static implicit operator DateTime?(MyDateTime myDateTime)
    {
        return myDateTime.DateTime;
    }

    public static implicit operator DateTime(MyDateTime myDateTime)
    {
        if (myDateTime.DateTime.HasValue)
        {
            return myDateTime.DateTime.Value;
        }
        else
        {
            return System.DateTime.MinValue;
        }
    }

    public static implicit operator MyDateTime(DateTime? dateTime)
    {
        return FromDateTime(dateTime);
    }

    public static implicit operator MyDateTime(DateTime dateTime)
    {
        return FromDateTime(dateTime);
    }
 }

如果我执行以下操作,则会调用隐式强制转换并且一切正常:

MyDateTime x= DateTime.Now; 

但是当我有一个两个对象,其中一个有DateTime而另一个有MyDateTime,我使用上面的代码将属性从一个对象复制到另一个对象时,它没有并生成一个错误,说明DateTime无法转换为MyTimeDate。

如何解决此问题?

1 个答案:

答案 0 :(得分:1)

应该工作的一个可怕方法是混合dynamic和反思:

private static T ConvertValue<T>(dynamic value)
{
    return value; // This will perform conversion automatically
}

然后:

var sourceValue = sourceProperty.GetValue(source, null);
if (sourceProperty.PropertyType != tp.PropertyType)
{
    var method = typeof(PropertyCopier).GetMethod("ConvertValue",
       BindingFlags.Static | BindingFlags.NonPublic);
    method = method.MakeGenericMethod(new[] { tp.PropertyType };
    sourceValue = method.Invoke(null, new[] { sourceValue });
}
tp.SetValue(target, sourceValue, null);

我们需要使用反射来使用正确的类型参数调用泛型方法,但动态类型将为您使用正确的转换运算符。

哦,最后一个请求:请不要在我的代码附近包含我的名字 ,无论是在评论,提交日志中。 AARGH。