Как бы вы улучшили этот класс поверхностного копирования?
-
19-08-2019 - |
Вопрос
Я написал класс с одним статическим методом, который копирует значения свойств из одного объекта в другой.Неважно, какого типа каждый объект, важно только то, что они имеют одинаковые свойства.Он делает то, что мне нужно, поэтому я не буду его разрабатывать дальше, но какие улучшения вы бы сделали?
Вот код:
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);
Решение
Ваши DTO сериализуются? Я ожидаю, что в таком случае:
MemberInfo[] sm = FormatterServices.GetSerializableMembers(typeof(From));
object[] data = FormatterServices.GetObjectData(from, sm);
FormatterServices.PopulateObjectMembers(to, sm, data);
Но учтите, что я не совсем согласен с таким общим подходом. Я бы предпочел сильный контракт на копирование ваших DTO, который реализует каждый DTO.
Другие советы
Измените имена параметров типа, чтобы они соответствовали соглашениям об именах, например.TFrom и TTo или TSource и TDest (или TDestination).
Выполняйте большую часть своей работы с использованием универсального типа, а не просто универсального метода.Это позволяет кэшировать свойства, а также позволяет выводить тип.Вывод типа важен для параметра «TFrom», поскольку он позволяет использовать анонимные типы.
Потенциально вы могли бы сделать это невероятно быстро, динамически генерируя код для копирования свойства и сохраняя его в делегате, допустимом для типа «from».Или потенциально сгенерировать его для каждой пары «от/в», что будет означать, что при фактическом копировании вообще не потребуется использовать отражение!(Подготовка кода потребует разового выполнения каждой пары типов, но, будем надеяться, у вас не будет слишком много пар.)
Новый метод, который создал новый экземпляр 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;
}
Решите, что вы хотите сделать, если переданы объекты типов, которые имеют некоторые свойства, но не все. Проверьте наличие свойства в объекте From
объекта To
, прежде чем пытаться установить его значение. Сделайте & Правильную вещь & Quot; когда вы приходите к собственности, которой не существует. Если все общедоступные свойства должны быть идентичны, вам необходимо проверить, все ли они установлены для объекта <=>, и обработать случай, когда вы этого не сделали соответствующим образом.
Я бы также предположил, что вы можете использовать атрибуты для украшения свойств, которые необходимо скопировать, и игнорировать другие. Это позволит вам легче перемещаться между двумя различными объектами и продолжать поддерживать некоторые общедоступные свойства, которые создаются, а не хранятся в вашем бизнес-объекте.