Вот насчет "рефлекшен _необходим_ только на первом шаге "получить"" — это вообще говоря не верно. Потому что, при вызове GetValue/SetValue каждый раз используется метаданные. И во втором примере, да...лямбда скомпилирована...но при каждом ее вызове будет вызываться type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic) опять же, каждый раз — рефлекшен. Насчет Assign я не знаю как он работает скорее всего по умному генерит код мапинга, только в этом случае будет быстрее чем в первом примере.
BLToolkit.Mapping ObjectToObject, без создания экземпляра.
Проблема в след: нужно отобразить один объект на другой (уже созданный), типы одинаковые. Для ссылочных типов копировать ссылки. Нашел в BLToolkit класс BLToolkit.Mapping.Map, он это делает, но создает каждый раз новый объект:
Здравствуйте, NNetman, Вы писали:
NN>Проблема в след: нужно отобразить один объект на другой (уже созданный), типы одинаковые. Для ссылочных типов копировать ссылки.
Тогда можно просто получить все поля объекта (Type::GetFields(BindingFlags.Instance|BindingFlags.NonPublic)), пройтись по ним и присвоить значения полей одного объекта полям другого:
using System;
using System.Reflection;
class Program
{
static void Main(string[] args) {
Action source = () => Console.WriteLine("Aaa");
Action target = () => Console.WriteLine("Bbb");
target(); // "Bbb"
Copy(source, target);
target(); // "Aaa"
}
static void Copy(object source, object target) {
if(source == null) {
throw new ArgumentNullException("source");
} else if(target == null) {
throw new ArgumentNullException("target");
} else if(source.GetType() != target.GetType()) {
throw new ArgumentException("source.GetType() != target.GetType()", "target");
}//ifvar type = source.GetType();
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
Array.ForEach(fields, field => field.SetValue(target, field.GetValue(source)));
}
}
Help will always be given at Hogwarts to those who ask for it.
Re: BLToolkit.Mapping ObjectToObject, без создания экземпля
Здравствуйте, NNetman, Вы писали:
NN>Проблема в след: нужно отобразить один объект на другой (уже созданный), типы одинаковые. Для ссылочных типов копировать ссылки. Нашел в BLToolkit класс BLToolkit.Mapping.Map, он это делает, но создает каждый раз новый объект: NN>DestObject = BLToolkit.Mapping.Map.ObjectToObject<Template>(SourceObject);
Там же есть перегрузка которая принимает destinationObject.
Re[2]: BLToolkit.Mapping ObjectToObject, без создания экзем
Здравствуйте, MozgC, Вы писали:
MC>Здравствуйте, NNetman, Вы писали:
NN>>Проблема в след: нужно отобразить один объект на другой (уже созданный), типы одинаковые. Для ссылочных типов копировать ссылки. Нашел в BLToolkit класс BLToolkit.Mapping.Map, он это делает, но создает каждый раз новый объект: NN>>DestObject = BLToolkit.Mapping.Map.ObjectToObject<Template>(SourceObject);
MC>Там же есть перегрузка которая принимает destinationObject.
Да, там есть перегрузка
public static T ObjectToObject<T>(object sourceObject, params object[] parameters);
Но вот parameters, это явно не destinationObject, что собственно и было проверенно имперически, не работает.
Re[3]: BLToolkit.Mapping ObjectToObject, без создания экзем
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, NNetman, Вы писали:
NN>>Да _FRED_, это вариант, но reflection меня не устраивает.
_FR>А каким же образом тулкит у вас маппинг делает?
Он использует reflection один раз, после чего на лету собирает сборку и подключает ее.
Re[5]: BLToolkit.Mapping ObjectToObject, без создания экзем
Здравствуйте, NNetman, Вы писали:
NN>>>Да _FRED_, это вариант, но reflection меня не устраивает. _FR>>А каким же образом тулкит у вас маппинг делает? NN>Он использует reflection один раз, после чего на лету собирает сборку и подключает ее.
Ага, значит всё-таки устраивает вас рефлекшен
Главное в моём ответе было "получить все поля объекта, пройтись по ним и присвоить значения полей одного объекта полям другого". И рефлекшен _необходим_ только на первом шаге "получить"
Не на пример надо было внимание обращать (пример лишь демонстрирует, что алгоритм в принципе рабочий), а подумать над подходящей вам реализацией алгоритма — данных в вопросе содержалось недостаточно, что бы учесть всё что вам на самом деле требуется.
Хочется побыстрее: пожалуйста, можно и вместо SetValue/GetValue использовать более современные методы:
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
class Program
{
static void Main(string[] args) {
Action source = () => Console.WriteLine("Aaa");
Action target = () => Console.WriteLine("Bbb");
target(); // "Bbb"
Copy(source, target);
target(); // "Aaa"
}
static void Copy<T>(T source, T target) {
if(source == null) {
throw new ArgumentNullException("source");
} else if(source.GetType() != typeof(T)) {
throw new ArgumentException("source.GetType() != typeof(T)", "source");
} else if(target == null) {
throw new ArgumentNullException("target");
} else if(source.GetType() != target.GetType()) {
throw new ArgumentException("source.GetType() != target.GetType()", "target");
}//ifvar copy = CreateMapper<T>();
copy(source, target);
}
static Action<T, T> CreateMapper<T>() {
var source = Expression.Parameter(typeof(T));
var target = Expression.Parameter(typeof(T));
var type = typeof(T);
var assigns =
from field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
let left = Expression.Field(target, field)
let right = Expression.Field(source, field)
select Expression.Assign(left, right);
var lambda = Expression.Lambda<Action<T, T>>(Expression.Block(assigns), source, target);
return lambda.Compile();
}
}
Остаётся только довести этот пример до удобоваримого (ну там Memoize прикрутить на получение маппера, научиться вызывать маппер с динамическим типом… но это уже за рамками данного обсуждения).
Help will always be given at Hogwarts to those who ask for it.
Re[3]: BLToolkit.Mapping ObjectToObject, без создания экзем
Здравствуйте, Аноним, Вы писали:
А>Вот насчет "рефлекшен _необходим_ только на первом шаге "получить"" — это вообще говоря не верно. Потому что, при вызове GetValue/SetValue каждый раз используется метаданные.
Под рефлекшеном понимается GetFields. По поводу GetValue/SetValue попробуйте всё-таки внимательно подумать о том, что я сказал в своём сообщении.
А>И во втором примере, да...лямбда скомпилирована...но при каждом ее вызове будет вызываться type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic) опять же, каждый раз — рефлекшен.
При вызове лямбды "GetFields" каждый раз вызываться не будет. Если вы считаете иначе, напишите код, который это продемонстрирует
А, вообще, вы моё сообщение до конца прочитать потрудились?
Help will always be given at Hogwarts to those who ask for it.
Re: BLToolkit.Mapping ObjectToObject, без создания экземпля
Здравствуйте, NNetman, Вы писали:
NN>Проблема в след: нужно отобразить один объект на другой (уже созданный), типы одинаковые. Для ссылочных типов копировать ссылки. Нашел в BLToolkit класс BLToolkit.Mapping.Map, он это делает, но создает каждый раз новый объект: