Необходимо копировать все публичные свойства из одного объекта в другой объект такого же типа. В результате раздумий родился следующий код.
public static class PropertyCopy<T> where T : new()
{
private static readonly PropertyInfo[] _propertyInfo;
static PropertyCopy()
{
_propertyInfo = typeof(T).GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance).Where(p => p.CanWrite).ToArray();
}
public static void CopyAllProperties(T from, T to)
{
foreach (var prop in _propertyInfo)
{
prop.SetValue(to, prop.GetValue(from));
}
}
}
Идея тут такая, когда впервые вызывается метод CopyAllProperties, в конструкторе создается массив со всеми необходимыми для копирования свойствами PropertyInfo[]. И при последующем вызове метода CopyAllProperties для этого типа массив создаваться уже не будет, все свойства уже выбраны и готовы в копированию. И по идее большая часть накладных расходов на производительность через reflection в данном случае снимается.
Копировать предполагается очень много раз, поэтому вопрос производительности важен. Копирование не нужно глубокое, то есть для ссылочного типа копируется ссылка.
Этот код вполне работает и выглядит красиво.
Правильное ли предположение про "большая часть накладных расходов на производительность через reflection в данном случае снимается"?
Либо все таки вся проблема будет в prop.SetValue(to, prop.GetValue(from))?
Нет. Основные расходы на reflection случаются не в момент GetProperties
(как раз метаданные средой выполнения кешируются), а при обращении к свойству через SetValue
и GetValue
.
Способ ускорения таких вещей известен - генерация кода на лету. Проще всего использовать Linq Expressions:
public static class PropertyCopy<T>
{
private static readonly Action<T, T> copier;
static PropertyCopy()
{
var p1 = Expression.Parameter(typeof(T), "from");
var p2 = Expression.Parameter(typeof(T), "to");
var props = from property in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
where property.CanRead && property.CanWrite
select Expression.Assign(Expression.Property(p2, property), Expression.Property(p1, property));
copier = Expression.Lambda<Action<T, T>>(Expression.Block(props), p1, p2).Compile();
}
public static void CopyAllProperties(T from, T to) => copier(from, to);
}
Имеется список кнопок, которые расположены одна под другой и не вмещающихся в видимую область на девайсахПри помощи Scroll Rect реализовано "проматывание"...
Доброго времени сутокСтолкнулся с проблемой:не могу подключить библиотеку в Visual Stidio
Есть приложение, в котором я хочу реализовать MVVMВ файле MainWindow
Помогите исправить ошибку в запросе: