Приведение во время выполнения с использованием неявной версии con - PullRequest
1 голос
/ 28 марта 2012

У меня есть следующий код, который копирует значения свойств из одного объекта в другой, сопоставляя имена их свойств:

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 Ответ

1 голос
/ 28 марта 2012

Один ужасный подход, который должен работать, состоит в том, чтобы смешать 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...