Лучший способ клонировать свойства разнородных объектов

У меня есть приложение MVC3, которое должно синхронизировать модели представления с моделями базы данных. Я обнаружил, что пишу слишком много кода, чтобы копировать свойства назад и вперед между различными объектами. Я избегал этого, когда мог просто разделить модель данных на подклассы, но иногда я обнаруживал, что это слишком ограничивает.

Я разработал несколько методов расширения для Object для поддержки мелкого клонирования свойств с похожими именами, и это сработало довольно хорошо. Однако мне интересно, есть ли более эффективные средства для достижения того же самого. Так что я думаю, что это требует экспертной оценки и вариантов улучшения этого кода.

ОБНОВЛЕНИЕ: я нашел, что лучше обрабатывать связанные таблицы явно. Тестирование IsVirtual предотвратит непреднамеренное изменение отношений во время клонирования. Смотрите обновленный метод CloneMatching. Другие явно указывают, какие свойства обновлять или исключать.

public static class CustomExtensions
{
   public static T CloneMatching<T, S>(this T target, S source)
       where T : class
       where S : class
    {
        if (source == null)
        {
            return target;
        }
        Type sourceType = typeof(S);
        Type targetType = typeof(T);
        BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;

        PropertyInfo[] properties = sourceType.GetProperties();
        foreach (PropertyInfo sPI in properties)
        {
            PropertyInfo tPI = targetType.GetProperty(sPI.Name,flags);
            if (tPI != null && tPI.PropertyType.IsAssignableFrom(sPI.PropertyType) && !tPI.PropertyType.IsVirtual)
            {
                tPI.SetValue(target, sPI.GetValue(source, null), null);
            }
        }
        return target;
    }

    public static T CloneProperties<T, S>(this T target, S source, string[] propertyNames)
       where T : class
       where S : class
    {
        if (source == null)
        {
            return target;
        }
        Type sourceType = typeof(S);
        Type targetType = typeof(T);
        BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;

        PropertyInfo[] properties = sourceType.GetProperties();
        foreach (PropertyInfo sPI in properties)
        {
            if (propertyNames.Contains(sPI.Name))
            {
                PropertyInfo tPI = targetType.GetProperty(sPI.Name, flags);
                if (tPI != null && tPI.PropertyType.IsAssignableFrom(sPI.PropertyType))
                {
                    tPI.SetValue(target, sPI.GetValue(source, null), null);
                }
            }
        }
        return target;
    }
    public static T CloneExcept<T, S>(this T target, S source, string[] propertyNames)
       where T : class
       where S : class
    {
        if (source == null)
        {
            return target;
        }
        Type sourceType = typeof(S);
        Type targetType = typeof(T);
        BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;

        PropertyInfo[] properties = sourceType.GetProperties();
        foreach (PropertyInfo sPI in properties)
        {
            if (!propertyNames.Contains(sPI.Name))
            {
                PropertyInfo tPI = targetType.GetProperty(sPI.Name, flags);
                if (tPI != null && tPI.PropertyType.IsAssignableFrom(sPI.PropertyType))
                {
                    tPI.SetValue(target, sPI.GetValue(source, null), null);
                }
            }
        }
        return target;
    }
}

Вот пример того, как я использую его для сопоставления модели представления с моделью данных.

DataSession.Quote.CloneProperties(viewModel,
                new[] {"PaymentType","CardHolder","CardHolderZip","CardNumber","CardExp","CVC",
                          "AccountHolder","AccountHolderZip","ABA","Account",
                          "AccuracyAgreement","PrivacyTermsAgreement","ElectronicSignatureAgreement"});

Ответы на вопрос(0)

Ваш ответ на вопрос