BLToolkit.Mapping ObjectToObject, без создания экземпляра.
От: NNetman  
Дата: 08.04.11 02:25
Оценка:
Проблема в след: нужно отобразить один объект на другой (уже созданный), типы одинаковые. Для ссылочных типов копировать ссылки. Нашел в BLToolkit класс BLToolkit.Mapping.Map, он это делает, но создает каждый раз новый объект:

DestObject = BLToolkit.Mapping.Map.ObjectToObject<Template>(SourceObject);







12.04.11 00:24: Перенесено модератором из '.NET' — TK
bltoolkit
Re: BLToolkit.Mapping ObjectToObject, без создания экземпля
От: _FRED_ Черногория
Дата: 08.04.11 02:38
Оценка:
Здравствуйте, 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");
    }//if

    var 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, без создания экземпля
От: MozgC США http://nightcoder.livejournal.com
Дата: 08.04.11 02:40
Оценка:
Здравствуйте, NNetman, Вы писали:

NN>Проблема в след: нужно отобразить один объект на другой (уже созданный), типы одинаковые. Для ссылочных типов копировать ссылки. Нашел в BLToolkit класс BLToolkit.Mapping.Map, он это делает, но создает каждый раз новый объект:

NN>DestObject = BLToolkit.Mapping.Map.ObjectToObject<Template>(SourceObject);


Там же есть перегрузка которая принимает destinationObject.
Re[2]: BLToolkit.Mapping ObjectToObject, без создания экзем
От: NNetman  
Дата: 08.04.11 04:04
Оценка:
Да _FRED_, это вариант, но reflection меня не устраивает.
Re[2]: BLToolkit.Mapping ObjectToObject, без создания экзем
От: NNetman  
Дата: 08.04.11 04:12
Оценка:
Здравствуйте, 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_ Черногория
Дата: 08.04.11 04:18
Оценка:
Здравствуйте, NNetman, Вы писали:

NN>Да _FRED_, это вариант, но reflection меня не устраивает.


А каким же образом тулкит у вас маппинг делает?
Help will always be given at Hogwarts to those who ask for it.
Re[4]: BLToolkit.Mapping ObjectToObject, без создания экзем
От: NNetman  
Дата: 08.04.11 04:30
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, NNetman, Вы писали:


NN>>Да _FRED_, это вариант, но reflection меня не устраивает.


_FR>А каким же образом тулкит у вас маппинг делает?



Он использует reflection один раз, после чего на лету собирает сборку и подключает ее.
Re[5]: BLToolkit.Mapping ObjectToObject, без создания экзем
От: _FRED_ Черногория
Дата: 08.04.11 04:57
Оценка:
Здравствуйте, 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");
    }//if

    var 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, без создания экзем
От: _FRED_ Черногория
Дата: 08.04.11 05:01
Оценка:
Здравствуйте, NNetman, Вы писали:

MC>>Там же есть перегрузка которая принимает destinationObject.

NN>Да, там есть перегрузка

Следите пожалуйста за оверквотингом в при написании ответов

NN>public static T ObjectToObject<T>(object sourceObject, params object[] parameters);

NN>Но вот parameters, это явно не destinationObject, что собственно и было проверенно имперически, не работает.

Там есть и такая перегрузка:
public static object ObjectToObject(object sourceObject, object destObject, params object[] parameters)
Help will always be given at Hogwarts to those who ask for it.
Re[6]: BLToolkit.Mapping ObjectToObject, без создания экзем
От: Аноним  
Дата: 08.04.11 12:41
Оценка: -1
Вот насчет "рефлекшен _необходим_ только на первом шаге "получить"" — это вообще говоря не верно. Потому что, при вызове GetValue/SetValue каждый раз используется метаданные. И во втором примере, да...лямбда скомпилирована...но при каждом ее вызове будет вызываться type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic) опять же, каждый раз — рефлекшен. Насчет Assign я не знаю как он работает скорее всего по умному генерит код мапинга, только в этом случае будет быстрее чем в первом примере.
Re[4]: BLToolkit.Mapping ObjectToObject, без создания экзем
От: NNetman  
Дата: 08.04.11 12:45
Оценка:
Да, действительно есть такая, нашел Спасибо.
Re[7]: BLToolkit.Mapping ObjectToObject, без создания экзем
От: _FRED_ Черногория
Дата: 08.04.11 12:47
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вот насчет "рефлекшен _необходим_ только на первом шаге "получить"" — это вообще говоря не верно. Потому что, при вызове 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, без создания экземпля
От: ili Россия  
Дата: 12.04.11 04:52
Оценка:
Здравствуйте, NNetman, Вы писали:

NN>Проблема в след: нужно отобразить один объект на другой (уже созданный), типы одинаковые. Для ссылочных типов копировать ссылки. Нашел в BLToolkit класс BLToolkit.Mapping.Map, он это делает, но создает каждый раз новый объект:


ExpressionMapper
Автор: IT
Дата: 03.03.10
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.