Как бы вы улучшили этот класс мелкого копирования? - PullRequest
5 голосов
/ 22 января 2009

Я написал класс с одним статическим методом, который копирует значения свойств из одного объекта в другой. Не имеет значения, какой тип у каждого объекта, только то, что они имеют идентичные свойства. Он делает то, что мне нужно, так что я не буду разрабатывать его дальше, но какие улучшения вы бы сделали?

Вот код:

public class ShallowCopy
{
    public static void Copy<From, To>(From from, To to)
        where To : class
        where From : class
    {
        Type toType = to.GetType();
        foreach (var propertyInfo in from.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance))
        {
            toType.GetProperty(propertyInfo.Name).SetValue(to, propertyInfo.GetValue(from, null), null);
        }
    }
}

Я использую его следующим образом:

EmployeeDTO dto = GetEmployeeDTO();
Employee employee = new Employee();
ShallowCopy.Copy(dto, employee);

Ответы [ 4 ]

6 голосов
/ 22 января 2009

Сериализуются ли ваши DTO? Я ожидаю, что в таком случае:

MemberInfo[] sm = FormatterServices.GetSerializableMembers(typeof(From));
object[] data = FormatterServices.GetObjectData(from, sm);
FormatterServices.PopulateObjectMembers(to, sm, data);

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

4 голосов
/ 22 января 2009
  • Измените имена параметров вашего типа в соответствии с соглашениями об именах, например, TFrom и TTo, или TSource и TDest (или TDestination).

  • Делайте большую часть своей работы в универсальном типе, а не просто в универсальном методе. Это позволяет вам кэшировать свойства, а также разрешать вывод типов. Вывод типа важен для параметра «TFrom», поскольку он позволяет использовать анонимные типы.

  • Вы могли бы сделать это ослепительно быстро, динамически генерируя код для копирования свойства и сохранения его в делегате, который действителен для типа «от». Или потенциально сгенерируйте его для каждой пары from / to, что означало бы, что фактическое копирование вообще не должно было бы использовать отражение! (Подготовка кода была бы одноразовым совпадением для пары типов, но, надеюсь, у вас не будет слишком много пар.)

2 голосов
/ 22 января 2009

Новый метод, который создал новый экземпляр To и вызвал метод Copy() перед возвратом, может быть полезным.

Как это:

public static To Create<From, To>(From from)
    where To : class, new()
    where From : class
{
    var to = new To();
    Copy(from, to);
    return to;
}
1 голос
/ 22 января 2009

Решите, что вы хотите сделать, если переданы объекты типов, которые имеют некоторые свойства, но не все. Проверьте наличие свойства в объекте From в объекте To, прежде чем пытаться установить его значение. Делайте «правильные вещи», когда вы придете к собственности, которой не существует. Если все общедоступные свойства должны быть идентичны, вам необходимо проверить, установлены ли все из них для объекта To, и обработать случай, когда вы этого не сделали соответствующим образом.

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

...