Mapping объектов
От: Dog  
Дата: 19.04.09 10:35
Оценка:
class A
{
  public int Id{get;set;}
}
class B
{
  public int Id{get;set;}
  public A A{get;set;}
}
class BMap
{
  public int Id{get;set;}
  public int AId{get;set;}
}

Как можно замапить B на BMap и обратно ? Вешать атрибуты на B и A нельзя.
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re: Mapping объектов
От: ili Россия  
Дата: 20.04.09 04:36
Оценка: 6 (1)
Здравствуйте, Dog, Вы писали:

Dog>Как можно замапить B на BMap и обратно ? Вешать атрибуты на B и A нельзя.


TypeExtension тебя должен спасти, позволяет настраивать маппинг через xml пример здесь
Re[2]: Mapping объектов
От: Dog  
Дата: 20.04.09 06:42
Оценка:
Dog>>Как можно замапить B на BMap и обратно ? Вешать атрибуты на B и A нельзя.
ili>TypeExtension тебя должен спасти, позволяет настраивать маппинг через xml пример здесь
а можно как-то в виде ?
class BMap
{
  public int Id{get;set;}
  [MapField("A.Id")]
  public int AId{get;set;}
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re[3]: Mapping объектов
От: ili Россия  
Дата: 20.04.09 07:41
Оценка:
Здравствуйте, Dog, Вы писали:

Dog>а можно как-то в виде ?


можно, от чего же нельзя...

давай рассмотрим все на примере того же теста итак, имеем:

// вот у нас класс, с мапингом, размеченым аттрибутами, обратим внимание на то, что имена полей не совпадают с теми что в БД
public class Person
{
    [PrimaryKey]
    [MapField("PersonID")]  public int    ID;
    [MapField("FirstName")] public string FName;
    [MapField("LastName")]  public string LName;
}

[Test]
public void Test()
{
    // вот тут мы делаем выборку из БД
    Person p = (Person)new SqlQuery().SelectByKey(typeof(Person), 1);
    
    // вот тут проверяем, что отмапилось все верно
    Assert.AreEqual(1,        p.ID);
    Assert.AreEqual("John",   p.FName);
    Assert.AreEqual("Pupkin", p.LName);

    // теперь начинается самое интересное
    // 1. создается маппинг схема, новая, зачем, все просто - экстеншены грузятся в схему, где и хранятся
    // пользуя для экстеншенов свою схему, мы как-бы не влиеям на дефолтную
    MappingSchema map = new MappingSchema();

    // 2. вот тут грузятся экстеншены из XML файла
    // что интересно - файл может как лежать "рядом" с приложением, так и быть ембеднутым ресурсом
    // сам файл приведен чуть ниже
    map.Extensions = TypeExtension.GetExtensions("XmlMap.xml");

    // вот тут мы мапим объект к ДатаРоу
    DataRow dr = map.MapObjectToDataRow(p, new DataTable());

    // а вот тут проверяем, что разметка полей _изменилась_ на ту, которую задает экстеншн
    Assert.AreEqual(1,        dr["PERSON_ID"]);
    Assert.AreEqual("John",   dr["FIRST_NAME"]);
    Assert.AreEqual("Pupkin", dr["LAST_NAME"]);
}


а вот собственно наша XML-ка... тут все прозачно до безобразия, комментировать не буду...

<?xml version="1.0" encoding="utf-8" ?> 
  <Types>
   <Type Name="Person">
    <Member Name="ID"    MapField="PERSON_ID" /> 
    <Member Name="FName" MapField="FIRST_NAME" /> 
    <Member Name="LName" MapField="LAST_NAME" /> 
   </Type>
  </Types>


такой экстеншн эквивалентен вот такой разметке аттрибутами:

public class Person
{
    [MapField("PERSON_ID")]  public int    ID;
    [MapField("FIRST_NAME")] public string FName;
    [MapField("LAST_NAME")]  public string LName;
}



все что можно задать в XML-ке задано 2 схемами:
Mapping.xsd — позволяет задать то, что относится к маппингу, имена полей, типы, значения по умолчанию и прочая шняга, в принцыпе оно там прямо так словами и перечислено, аттрибуты совпадают с аттрибутами полей (простите за тафтологию), разобраться достаточно просто
DataAccess.xsd — тут про датааксесс, тэйбл неймы, примари кеи, нон апдейтаблы

посмотрите в тестах *.xml, думаю, после этой короткой вводной разобраться не составит труда, если что — вэлкам, спрашивйте
Re[4]: Mapping объектов
От: Dog  
Дата: 20.04.09 13:08
Оценка:
ili>посмотрите в тестах *.xml, думаю, после этой короткой вводной разобраться не составит труда, если что — вэлкам, спрашивйте
У меня MapObjectToObject. С xml я понял, поковыряюсь на досуге. Меня интересует как расширить существующую функциональность, что бы можно было помечать атрибутами. (для самых простых случаев, без всяких там циклических ссылок и т.д...)
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re[5]: Mapping объектов
От: ili Россия  
Дата: 21.04.09 02:13
Оценка:
Здравствуйте, Dog, Вы писали:

Dog>У меня MapObjectToObject. С xml я понял, поковыряюсь на досуге. Меня интересует как расширить существующую функциональность, что бы можно было помечать атрибутами. (для самых простых случаев, без всяких там циклических ссылок и т.д...)


все едино... в смысле весь мапинг — единообразен, и разницы м\д ОбдектТуОбджект, или ОбджектТуДатаРоу — по сути нет.

в какую сторону расширить-то? чего не хватат? =)
Re[6]: Mapping объектов
От: Dog  
Дата: 21.04.09 07:53
Оценка:
Dog>>У меня MapObjectToObject. С xml я понял, поковыряюсь на досуге. Меня интересует как расширить существующую функциональность, что бы можно было помечать атрибутами. (для самых простых случаев, без всяких там циклических ссылок и т.д...)
ili>все едино... в смысле весь мапинг — единообразен, и разницы м\д ОбдектТуОбджект, или ОбджектТуДатаРоу — по сути нет.
ili>в какую сторону расширить-то? чего не хватат? =)
Не хватает маппинга на поля вложенных объектов не юзая xml. Смотри первый пост
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re[7]: Mapping объектов
От: ili Россия  
Дата: 21.04.09 08:01
Оценка: 4 (1)
Здравствуйте, Dog, Вы писали:

Dog>Не хватает маппинга на поля вложенных объектов не юзая xml. Смотри первый пост


эмн... там про атрибуты было, а про xml ничего

вообще если еще и без XML (читать метаданные) то, в общем случае, нужен телепатический модуль...

а вообще можно попробовать сварганить свой мапер раздел Map &amp; MappingSchema подраздел Семейства Map
Re[8]: Mapping объектов
От: Dog  
Дата: 21.04.09 12:34
Оценка:
Dog>>Не хватает маппинга на поля вложенных объектов не юзая xml. Смотри первый пост
ili>эмн... там про атрибуты было, а про xml ничего
ili>вообще если еще и без XML (читать метаданные) то, в общем случае, нужен телепатический модуль...
Нет, общий случай не надо А в чём там могут быть проблемы ?

ili>а вообще можно попробовать сварганить свой мапер раздел Map &amp; MappingSchema подраздел Семейства Map

Угу, видимо это и надо...
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re[9]: Mapping объектов
От: ili Россия  
Дата: 21.04.09 12:39
Оценка:
Здравствуйте, Dog, Вы писали:

ili>>вообще если еще и без XML (читать метаданные) то, в общем случае, нужен телепатический модуль...

Dog>Нет, общий случай не надо А в чём там могут быть проблемы ?

нуу... ходят слухи, что постоянные занятия телепатией приводят к образованию раковых опухолей мозга у людей, и выгоранию процессоров и памяти у компов

а если серъезно, то проблема одна — как без метадаты понять чо делать?
вот в твоем примере, через какое место можно сообразить, что B.A.Id <=> BMap.AId?
метадата — задает правила, а если нет правил, то, в общем случае, все неправильно (по определению )
Re[10]: Mapping объектов
От: Dog  
Дата: 21.04.09 13:07
Оценка:
ili>а если серъезно, то проблема одна — как без метадаты понять чо делать?
ili>вот в твоем примере, через какое место можно сообразить, что B.A.Id <=> BMap.AId?
Как-то так...
class A
{
  public int Id{get;set;}
}
class B
{
  public int Id{get;set;}
  public A Aa{get;set;}
}
class BMap
{
  public int Id{get;set;}
  [MapField("Aa.Id")]
  public int AId{get;set;}
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re[10]: Mapping объектов
От: Dog  
Дата: 21.04.09 15:31
Оценка:
ili>вот в твоем примере, через какое место можно сообразить, что B.A.Id <=> BMap.AId?
Разобрался с Xml всё работает (не скажу что было тривиально ) Получилось что-то в виде:
<Types>
  <Type Name="B">
    <MapField MapName="Aa.ID" OrigName="Aa.ID" />
  </Type>
  <Type Name="BMap">
    <Member Name="Aa_ID" MapField="Aa.ID" />
  </Type>
</Types>


Смотрю в сорцы и меня мучает вопрос. Как кошернее расширить функциональность ?
Набросал быстро вот это, но не совсем нравиццо.
    public class ObjectMapperEx : ObjectMapper
    {
        public void UpdateMapper(IEnumerable<string> names)
        {
            foreach (var name in names)
            {
                var mm = GetComplexMapper(name, name);
                if (mm != null)
                {
                    Add(mm);
                }
            }
        }
        public IEnumerable<string> GetMapFields()
        {
            var names = new List<string>();
            foreach (MemberAccessor ma in TypeAccessor)
            {
                if (GetMapIgnore(ma))
                {
                    continue;
                }
                var mapFieldAttr = ma.GetAttribute<MapFieldAttribute>();
                if (mapFieldAttr != null)
                {
                    names.Add(mapFieldAttr.MapName);
                }
            }
            return names;
        }
    }
    public class MappingSchemaEx : MappingSchema
    {
        protected override ObjectMapper CreateObjectMapperInstance(Type type)
        {
            return new ObjectMapperEx();
        }
        public object MapObjectToObject(object sourceObject,object destObject)
        {
            var dest = (ObjectMapperEx)GetObjectMapper(destObject.GetType());
            var source = (ObjectMapperEx)GetObjectMapper(sourceObject.GetType());
            source.UpdateMapper(dest.GetMapFields());
            MapInternal(null,source, sourceObject,dest, destObject);
            return destObject;
        }
    }

Кто там у нас главный идеолог ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re[11]: Mapping объектов
От: ili Россия  
Дата: 21.04.09 16:46
Оценка:
Здравствуйте, Dog, Вы писали:

Dog>Как-то так...


ну тык почти
мапинг работает по алиасам, т.е. то у чего одинаковые алиасы считается "про одно и тоже"
по умолчанию в поля, которые мапятся попадают, грубо говоря, скалярные типы.
так что если сделать так, то все должно арбайтен:

class A
{
  public int Id{get;set;}
}
[MapField("AId", "Aa.Id")]
class B
{
  public int Id{get;set;}
  public A Aa{get;set;}
}
class BMap
{
  public int Id{get;set;}
  public int AId{get;set;}
}


хмл-ка что-то типа этого, должно сработать:

<Types>
  <Type Name="B">
    <MapField MapName="AId" OrigName="Aa.Id" />
  </Type>
</Types>


и таки допилвать ничо не надо
Re[12]: Mapping объектов
От: Dog  
Дата: 22.04.09 07:00
Оценка:
ili>ну тык почти
ili>мапинг работает по алиасам, т.е. то у чего одинаковые алиасы считается "про одно и тоже"
ili>по умолчанию в поля, которые мапятся попадают, грубо говоря, скалярные типы.
Это я уже понял. Теперь вопрос стоит, как, с точки зрения архитектуры, привильнее подключить ComplexMapper ?
Я написал решение
Автор: Dog
Дата: 21.04.09
, но оно мне не совсем нравится. Может лучше было бы сделать свой MetadataProvider или ещё как...

ili>так что если сделать так, то все должно арбайтен:

[MapField("AId", "Aa.Id")]
class B
{
  public int Id{get;set;}
  public A Aa{get;set;}
}

Вот как раз так сделать и нельзя
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re[11]: Mapping объектов
От: ili Россия  
Дата: 22.04.09 09:15
Оценка:
Здравствуйте, Dog, Вы писали:

Dog>Разобрался с Xml всё работает (не скажу что было тривиально ) Получилось что-то в виде:


ничо не понимаю... все и так работает, и ничего допиливать не надо...

        public class A
        {
            public int Id { get; set; }
        }
        public class B
        {
            public B()
            {
                Aa = new A();
            }

            public int Id  { get; set; }
            public A   Aa  { get; set; }
        }
        public class BMap
        {
            public int Id  { get; set; }
            public int AId { get; set; }
        }

        [Test]
        public void Test1()
        {
            B b = new B();

            b.Id    = 1;
            b.Aa.Id = 2;

            MappingSchema m = new MappingSchema();

            m.Extensions = TypeExtension.GetExtensions("Extension.xml");

            BMap bm = m.MapObjectToObject<BMap>(b);

            Assert.AreEqual(b.Id,    bm.Id);
            Assert.AreEqual(b.Aa.Id, bm.AId);

            B newB = m.MapObjectToObject<B>(bm);

            Assert.AreEqual(b.Id,    newB.Id);
            Assert.AreEqual(b.Aa.Id, newB.Aa.Id);
        }


Extension.xml

<?xml version="1.0" encoding="utf-8" ?>
<Types>
    <Type Name="B">
        <MapField MapName="AId" OrigName="Aa.Id" />
    </Type>
</Types>
Re[12]: Mapping объектов
От: Dog  
Дата: 22.04.09 12:04
Оценка:
Dog>>Разобрался с Xml всё работает (не скажу что было тривиально ) Получилось что-то в виде:
ili>ничо не понимаю... все и так работает, и ничего допиливать не надо...
Я писал, что разобрался с xml. Теперь мне интересно как правильно сделать без xml.
Что-нибудь ещё не понятно ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re[13]: Mapping объектов
От: ili Россия  
Дата: 22.04.09 12:36
Оценка: :)
Здравствуйте, Dog, Вы писали:

Dog>Я писал, что разобрался с xml. Теперь мне интересно как правильно сделать без xml.

Dog>Что-нибудь ещё не понятно ?

дыы... ты меня окончательно запутал мне терь ваще ничо непонятно =))

писать свой обджект маппер
ну то что ты там пару постов выше нарисовал, то поркуа бы не па, тока ниясно зачем всегда вызывать UpdateMapper? есть метод Init в нем заполняются мембер маперы, его можно успешно допилить.
ток вызывается он вроде всего один раз при создании обджект мапера, если у тебя правила не меняются, то лучше мембер маперы дозаполнять в нем.
Re[14]: Mapping объектов
От: Dog  
Дата: 22.04.09 15:56
Оценка:
ili>дыы... ты меня окончательно запутал мне терь ваще ничо непонятно =))
Ну вот опять
Есть задача сделать мапинг объект на объект не используя xml. Понятно ?
Вот такие классы. (мапинг B <-> BMap). Понятно ?
class A
{
  public int Id{get;set;}
}
class B
{
  public int Id{get;set;}
  public A Aa{get;set;}
}
class BMap
{
  public int Id{get;set;}
  public int AId{get;set;}
}

На А и В атрибуты вешать нельзя. Понятно ?
Метадату я описал так
class BMap
{
  public int Id{get;set;}
 [MapField("Aa.Id")]
  public int AId{get;set;}
}

В этом случае BMap -> B мапится, а наоборот — нет.
Вот вроде и всё...

ili>писать свой обджект маппер

ili>ну то что ты там пару постов выше нарисовал, то поркуа бы не па, тока ниясно зачем всегда вызывать UpdateMapper?
ili>есть метод Init в нем заполняются мембер маперы, его можно успешно допилить.
Можно. Я как раз хотел заюзать GetComplexMapper(string mapName, string origName) , чтобы не изобретать свой
Но не понял как мне получить в Init mapName и origName (в нашем случае они будут равны). Поэтому я пробежался по destObject получил mapName у MapField и обновил мембер маперы у sourceObject.
Ессно, мне это не нравиццо. Вот я и спрашиваю, как можно лучше?

ili>ток вызывается он вроде всего один раз при создании обджект мапера, если у тебя правила не меняются, то лучше мембер маперы дозаполнять в нем.

Это ясно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re[15]: Mapping объектов
От: ili Россия  
Дата: 23.04.09 04:45
Оценка:
Здравствуйте, Dog, Вы писали:

Dog>Есть задача сделать мапинг объект на объект не используя xml. Понятно ?


а кроме хмл можно чо-нить юзать? =))

Dog>На А и В атрибуты вешать нельзя. Понятно ?


ну низя, так низя

Dog>Метадату я описал так

Dog>
Dog>class BMap
Dog>{
Dog>  public int Id{get;set;}
Dog> [MapField("Aa.Id")]
Dog>  public int AId{get;set;}
Dog>}
Dog>

Dog>В этом случае BMap -> B мапится, а наоборот — нет.
Dog>Вот вроде и всё...

вот те еще вариант, если нельзя получать TypeExtension из XML, то почему бы его не формировать на основе BMap?
Re[16]: Mapping объектов
От: Dog  
Дата: 23.04.09 07:48
Оценка:
ili>вот те еще вариант, если нельзя получать TypeExtension из XML, то почему бы его не формировать на основе BMap?
Мы конечно не ищем лёгких путей, но это уже слишком
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.