[ANN] Emit Mapper
От: mrTwister Россия  
Дата: 18.11.09 21:00
Оценка: 65 (9)
http://emitmapper.codeplex.com

Emit Mapper — это мощная легковесная библиотека для проецирования одних объектов на другие. Имеет следующие особенности:

1) Очень быстрая. Работает через Emit с производительностью рукописного кода. По разным тестам в 150-600 раз быстрее чем AutoMapper. Бенчмарк

2) Очень гибкая. Проецировать можно что угодно на что угодно. Например, датаридер на объекты, объекты на SQL команды (UPDATE, INSERT), объекты на строку (сериализация), строку на объекты (десериализация) и так далее. Короче говоря, в рантайме можно задать произвольный меппинг чего угодно на что угодно, который работает со скоростью рукописного кода.
лэт ми спик фром май харт
Re: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 03.01.10 05:07
Оценка: 59 (5)
Здравствуйте, mrTwister, Вы писали:

T>http://emitmapper.codeplex.com


Совсем не плохо.

Там где можно дженерик методы можно было бы переписать следующим образом:

static class MapperImpl<TFrom,TTo>
{
    public static ObjectsMapper<TFrom,TTo> Instance = new ObjectsMapper<TFrom, TTo>(
        new ObjectsMapperManager().GetMapperImpl(
            typeof(TFrom),
            typeof(TTo),
            DefaultMapConfig.Instance
        )
    );
}

public ObjectsMapper<TFrom, TTo> GetMapper<TFrom, TTo>()
{
    return MapperImpl<TFrom,TTo>.Instance;
}

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

Сравнительный тест с BLT конечно же слегка наивен. В тесте BLT тестируется не столько маппинг, сколько время доступа к мапперу. Впрочем, обо всём по порядку.

T>Имхо, заставлять вешать атрибуты — это еще больший моветон. Это примерно как заставлять наследоваться от специального класса. Тем более, что ничто не мешает реализовать требуемую функциональность своими силами на основе Emit Mapper.


Этот подход ведёт в никуда. Пользователям нужна готовая функциональность, а не потенциальная возможность. Это я как собаковод говорю. "ничто не мешает реализовать" в 99.99% случаев означает, что никто ничего реализовывать никогда и не будет. Более того, разработчик инструмента должен держать своё мнение о моветонах при себе. Учить пользователей жизни — это не его работа. Нормальное объяснение отсутсвия какой-либо функциональности в инструменте это: лень, нет времени, технические проблемы, отсутствие выгоды и т.п. "еще больший моветон" можно обсуждать у нас в Философии и желательно вне контекста конкретного инструмента.

T>Как раз как маппер, БЛТ довольно слабый (ценность БЛТ не в маппере). Он не поддерживает даже вложенные объекты, не конфигурируется и т.д. По крайней мере не справился даже с такой простой задачкой:


Как раз как маппер, в реальных сценариях BLT даст фору кому угодно. "Даже вложенные объекты" в BLT не поддерживаются по-умолчанию. Кстати, они не поддерживаются по-умолчанию практически нигде, т.к. это вызывает больше проблем, чем бенефитов. Научить BLT справляться с поставленной задачкой можно, например, следующим образом:

[MapField("str2", "i.str2")]
public class Destination
{
    public class Int
    {
        public string str2;
    }

    public string str1;
    public Int i = new Int();
}

[MapField("str2", "i.str2")]
public class Source
{
    public class Int
    {
        public string str2 = "B1::Int::str2";
    }

    public string str1 = "B1::str1";
    public Int i = new Int();
}

T>Да и производительность у БЛТ маппера оставляет желать лучшего. На простеньком тесте (класс без вложеных объектов) БЛТ оказался в 250 раз медленнее. Вот код теста:

Думаю, любому взрослому и умному человеку, заинтересованному в конечном результате, обязательно захотелось бы найти объснению такому чудовищному отставанию в производительности и разобраться что же происходит на самом деле, а не отмазываться фразами вроде "Дак это проблемы BLT. Он другого интерфейса не предоставляет.". Тем более, что и интерфейс такой у BLT есть и у EM есть интерфейс, который поставил бы библиотеки в одинаковые условия. И тогда 250 раз мгновенно уменьшились бы на 125. Хотя проблема, конечно, не в этом.

Разница в производительности объясняется прежде всего тем, что в тесте EM тестируется только маппер, а в тесте BLT тестируется не столько маппер, сколько способ его получения. API для получения маппера как это происходит в сценарии в BLT попросту отсутствует. Не то что бы это было трудно сделать, но просто за 8 лет существования библиотеки это пока никому не было нужно. Сценариев где нужен маппинг одного объектв в другой не так много, высокопроизводительных сценариев ещё меньше, а когда они реально возникают, то написать код вручную, особенно сегодня при наличии инициализаторов в C# не представляет особой сложности.

В общем, BLT под такие сценарии никогда не оптимизировался. Другое дело вот такие сценарии:

public class A2
{
    public string str1;
    public string str2;
    public string str3;
    public string str4;
    public string str5;
    public string str6;
    public string str7;
    public string str8;
    public string str9;

    public int n1;
    public int n2;
    public int n3;
    public int n4;
    public int n5;
    public int n6;
    public int n7;
}

public class B2
{
    public string str1 = "str1";
    public string str2 = "str2";
    public string str3 = "str3";
    public string str4 = "str4";
    public string str5 = "str5";
    public string str6 = "str6";
    public string str7 = "str7";
    public string str8 = "str8";
    public string str9 = "str9";

    public int n1 = 1;
    public long n2 = 2;
    public short n3 = 3;
    public byte n4 = 4;
    public decimal n5 = 5;
    public float n6 = 6;
    public int n7 = 7;

}

static long BenchBLToolkit_List(int mappingsCount)
{
    var list = new List<B2>();

    for (var i = 0; i < mappingsCount; i++)
        list.Add(new B2());

    var sw = new Stopwatch();
    sw.Start();

    var dest = Map.ListToList<A2>(list);

    sw.Stop();
    return sw.ElapsedMilliseconds;
}

static long EmitMapper_List(int mappingsCount)
{
    var list = new List<B2>();

    for (var i = 0; i < mappingsCount; i++)
        list.Add(new B2());

    var sw = new Stopwatch();
    sw.Start();

    var mapper = ObjectsMapperManager.DefaultInstance.GetMapper<B2, A2>();
    var dest   = new List<A2>();

    foreach (var item in list)
        dest.Add(mapper.Map(item));

    sw.Stop();
    return sw.ElapsedMilliseconds;
}

Здесь мы уже имеем разницу не в 250 раз, а около двух, хотя и не в пользу BLT. Оставшаяся разница объясняется тем, что BLT делает больше проверок в рантайм. Например, если изменить приведённый выше код следующим образом, то EM упадёт:

public class B2
{
    ...
    public decimal? n5 = null;
    ....
}

Некоторые из этих проверок можно сократить только генерацией кода под каждый конкретный вариант использования, что практически не имеет смысла если не кешировать каким-то образом сам вариант использования или явно не напрягать пользователя, что бы он его как-то идентифицировал. В приведённых выше тестах EM именно этим и занимается. Это хорошо работает с объектами, но не работает с источниками данных, структура которых становится известной только в момент выполнения. К таким источникам относятся, например, базы данных. Кстати, давайте посмотрим что у нас с базами данных:

static long BLToolkit_DB(int mappingsCount)
{
    DbManager.AddConnectionString("data source=.;initial catalog=Northwind;integrated security=SSPI;");

    var sw = new Stopwatch();
    sw.Start();

    for (var i = 0; i < mappingsCount; i++)
    {
        using (var db = new DbManager())
        {
            var list = db
                .SetCommand("SELECT * FROM Customers")
                .ExecuteList<Customers>();
        }
    }

    sw.Stop();
    return sw.ElapsedMilliseconds;
}

static long EmitMapper_DB(int mappingsCount)
{
    var sw = new Stopwatch();
    sw.Start();

    for (var i = 0; i < mappingsCount; i++)
    {
        using(var con = new SqlConnection("data source=.;initial catalog=Northwind;integrated security=SSPI;"))
        using(var cmd = con.CreateCommand())
        {
            con.Open();

            cmd.Connection  = con;
            cmd.CommandType = System.Data.CommandType.Text;
            cmd.CommandText = "SELECT * FROM Customers";

            using (var reader = cmd.ExecuteReader())
            {
                var list  = reader.ToObjects<Customers>(null).ToList();
            }
        }
    }

    sw.Stop();
    return sw.ElapsedMilliseconds;
}

В этом примере EM уже начинает отставать. Скорее всего reader.ToObjects, взятый из примеров библиотеки не очень хорош. При этом он не очень хорош будучи написанным самим автором библиотеки, а что будет написано, если будет, пользователями, плохо знакомыми как с самой библиотекой, так и с базами данных?

В общем, библиотеку нужно допиливать под реалии. С синтетическими тестами она уже справляется хорошо, т.е. задел есть и надо признать задел неплохой.

Ну и в заключении, вот такие примеры в качестве сценарии использования библиотеки из документации лучше убрать:

public DTOCustomer GetCustomer(Guid customerId)
{
    using (var dc = new DataContext())
    {
        var customer = dc.Customers.Where(c => c.CustomerID == customerId).Single();
        return ObjectsMapperManager.DefaultInstance.GetMapper<Customer, DTOCustomer>().Map(customer);
    }
}

И в самом самом заключении, ObjectsMapperManager — это немного не по-английски.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 18.11.09 22:14
Оценка: 9 (2) +1
Здравствуйте, Holms, Вы писали:
H>Всё понравилось, кроме того как вы сделали Ignoring members
H>имхо писать имена как простая строка это плохой моветон.
H>Я бы добавил ещё атрибуты для полей которые не надо копировать.


H>
H>var a = ObjectsMapperManager.DefaultInstance.GetMapper<B, A>(
H>        new DefaultMapConfig().IgnoreMembers<B, A>(new[]{"str1"})
H>    ).Map(new B());
H>


Имхо, заставлять вешать атрибуты — это еще больший моветон. Это примерно как заставлять наследоваться от специального класса. Тем более, что ничто не мешает реализовать требуемую функциональность своими силами на основе Emit Mapper. Самый простой путь — это тупо отнаследоваться от DefaultMapConfig и переопределить логику игнора с учетом своих собственных требований и пожеланий (это могут быть не только атрибуты):

// Это наш собственный атрибут. Нас никто не заставляет использовать атрибуты, но допустим удобней/привычнее
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class MyIgnoreAttribute : Attribute
{
}

// Класс-оригинал
public class IgnoreByAttributesSrc
{
    // Делаем так, чтобы первое поле не копировалось
    [MyIgnoreAttribute]
    public string str1 = "IgnoreByAttributesSrc::str1";

    public string str2 = "IgnoreByAttributesSrc::str2";
}

// Класс-копия
public class IgnoreByAttributesDst
{
    public string str1 = "IgnoreByAttributesDst::str1";
    public string str2 = "IgnoreByAttributesDst::str2";
}

public class MyConfigurator : DefaultMapConfig
{
    //Переопределяем метод, который вызывается для конфигурирования меппинга и добавляем вызов IgnoreMembers
    //в соответствии с нашей логикой - атрибутом
    public override IMappingOperation[] GetMappingOperations(Type from, Type to)
    {
        base.IgnoreMembers<object, object>(GetIgnoreFields(from).Concat(GetIgnoreFields(to)).ToArray());
        return base.GetMappingOperations(from, to);
    }

    //Метод возвращает список полей и свойств, помеченных атрибутом
    private IEnumerable<string> GetIgnoreFields(Type type)
    {
        return type
            .GetFields()
            .Where(
                f => f.GetCustomAttributes(typeof(MyIgnoreAttribute), false).Length > 0
            )
            .Select(f => f.Name)
            .Concat(
                type
                .GetProperties()
                .Where(
                    p => p.GetCustomAttributes(typeof(MyIgnoreAttribute), false).Length > 0
                )
                .Select(p => p.Name)
            );
    }
}

[TestMethod]
public void Test()
{
    var mapper = ObjectsMapperManager.DefaultInstance.GetMapper<IgnoreByAttributesSrc, IgnoreByAttributesDst>(new MyConfigurator());
    var dst = mapper.Map(new IgnoreByAttributesSrc());
    Assert.AreEqual("IgnoreByAttributesDst::str1", dst.str1);
    Assert.AreEqual("IgnoreByAttributesSrc::str2", dst.str2);
}


Короче говоря, при проектировании Emit Mapper делалась ставка на то, что у каждого есть свое мнение на то, как должна выглядеть идеальная библиотека для маппинга. И вместо предоставления швейцарского ножа с миллионом возможностей включая заваривание кофе, Emit Mapper предоставляет своего рода фреймворк, который каждый может использовать для построения маппинга с учетом своих собственных требований. В семплах есть пример, когда генерируется маппер для объектов на дбридер используя штатные механизмы расширения. В этом основная "фишка" библиотеки.
лэт ми спик фром май харт
Re: [ANN] Emit Mapper
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 18.11.09 21:59
Оценка: +1 -1
Здравствуйте, mrTwister, Вы писали:

T>http://emitmapper.codeplex.com


T>Emit Mapper — это мощная легковесная библиотека для проецирования одних объектов на другие. Имеет следующие особенности:


T>1) Очень быстрая. Работает через Emit с производительностью рукописного кода. По разным тестам в 150-600 раз быстрее чем AutoMapper. Бенчмарк


T>2) Очень гибкая. Проецировать можно что угодно на что угодно. Например, датаридер на объекты, объекты на SQL команды (UPDATE, INSERT), объекты на строку (сериализация), строку на объекты (десериализация) и так далее. Короче говоря, в рантайме можно задать произвольный меппинг чего угодно на что угодно, который работает со скоростью рукописного кода.


Бегло просмотрел. Вывод — BLToolkit круче
[КУ] оккупировала армия.
Re[7]: [ANN] Emit Mapper
От: Jack128  
Дата: 03.01.10 08:03
Оценка: +2
Здравствуйте, Holms, Вы писали:

IT>>Что нужнее, DML или SL?

H>что скрывается под DML?

update/insert/delete запросы. И они нужнее -)
Re[6]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 04.01.10 15:01
Оценка: +2
Здравствуйте, AndrewVK, Вы писали:

AVK>А это вовсе не вопрос, потому что проблемы с конкретной удочкой вполне решаемы написанием собственной удочки в крайнем случае.



Прекрасно. Сколько надо написать кода для маппинга вложенных структур (в том числе рекурсивных)?
лэт ми спик фром май харт
Re[2]: [ANN] Emit Mapper
От: Holms США  
Дата: 03.01.10 05:51
Оценка: 58 (1)
Здравствуйте, IT, Вы писали:

пост не в тему, но
последняя версия BL из svn не компилится, можете поправить
вот пара ошибок

 EditableObjects\NotifyCollectionChangeTest.cs(497,48): error CS0433: The type 'System.Collections.Specialized.NotifyCollectionChangedEventArgs' exists in both 'f:\svn\bl-toolkit\Source\bin\Release\BLToolkit.3.dll' and 'c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll'
EditableObjects\NotifyCollectionChangeTest.cs(62,58): error CS0433: The type 'System.Collections.Specialized.NotifyCollectionChangedEventArgs' exists in both 'f:\svn\bl-toolkit\Source\bin\Release\BLToolkit.3.dll' and 'c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll'
EditableObjects\NotifyCollectionChangeTest.cs(446,52): error CS0433: The type 'System.Collections.Specialized.NotifyCollectionChangedEventArgs' exists in both 'f:\svn\bl-toolkit\Source\bin\Release\BLToolkit.3.dll' and 'c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll'
Done Building Project "F:\svn\bl-toolkit\UnitTests\CS\UnitTests.CS.csproj" (default targets) -- FAILED.
Project "F:\svn\bl-toolkit\BLToolkit.2008.sln" (1) is building "F:\svn\bl-toolkit\UnitTests\Linq\UnitTests.Linq.csproj" (13) on node 0 (default targets).
  Processing 0 EDMX files.
  Finished processing 0 EDMX files.
ConvertTest.cs(7,22): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
CompileTest.cs(7,22): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
MathFunctions.cs(3,22): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
Exceptions\Inheritance.cs(6,22): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
Model\NorthwindDB.cs(4,22): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
Exceptions\Mapping.cs(5,22): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
Functions.cs(7,22): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
DateTimeFunctions.cs(6,22): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
StringFunctions.cs(8,22): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
TestDbManager.cs(4,22): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
WhereTest.cs(11,23): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'BLToolkit.Data' (are you missing an assembly reference?)
Model\NorthwindDB.cs(14,10): error CS0246: The type or namespace name 'Table' could not be found (are you missing a using directive or an assembly reference?)
Model\NorthwindDB.cs(15,10): error CS0246: The type or namespace name 'Table' could not be found (are you missing a using directive or an assembly reference?)
Model\NorthwindDB.cs(16,10): error CS0246: The type or namespace name 'Table' could not be found (are you missing a using directive or an assembly reference?)



Кстати, какие планы насчет Silverlight-а. Будет поддержка?
Спасибо
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[5]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 05.01.10 06:34
Оценка: 18 (1)
Здравствуйте, Holms, Вы писали:

H>Кстати, будешь еще оптимизировать Linq реализацию, а то судя по первой таблице здесь BLToolkit не слишком скоростной.


Первая таблица — это не скорость. Это полнота поддержки Linq. Скорость во второй таблице. Это всё результаты на начало ноября. На сегодняшний день они выглядят следующим образом:

LINQ tests:
  Testing: BLToolkit (BLT)
  Testing: ADO.NET Entity Framework (EF)
  Testing: DataObjects.Net (DO)
  Testing: LightSpeed (LS)
  Testing: LINQ to SQL (L2S)
  Testing: NHibernate (NH)
  Testing: OpenAccess (OA)

LINQ tests scorecard:
                                       BLT        EF        DO        LS       L2S        NH        OA   Maximum      Unit
LINQ Implementation:            
  Aggregates                             3         0         0         3         0         3         2         5       f/a
  All/Any/Contains                       5         3         0         6         1       4/2         4         6       f/a
  Complex                                6         1         0         6         0         6         5         6       f/a
  Element operations                     5         4         0         6         2         6         5         9       f/a
  Filtering                              0       4/2         0       5/5       2/2       6/1         2        12       f/a
  Grouping                               2         1         0        10         1      10/2         5        10       f/a
  Join                                   2         1         0         4         0         4         2         4       f/a
  Ordering                               0       2/1         0       5/1         2         6         3         8       f/a
  Projections                          3/1       3/1       3/3       9/2       2/1       6/1         3        13       f/a
  References                             1         0         0         4         0         3         1         4       f/a
  Set operations                         0         0         0       5/1         0       6/2       4/1         9       f/a
  Standard functions                     0        12         2        12       3/1        20       9/1        25       f/a
  Take/Skip                              1         1         0       2/1         0       2/1         2         5       f/a
  Type casts                             0         1         0       3/1         1         4         2         5       f/a
Total:                          
  Performed                            121       121       121       121       121       121       121       121         #
  Passed                                93        88       116        41       107        35        72       121         #
  Failed                                28        33         5        80        14        86        49       121         #
    Properly                            27        29         2        69        10        77        47       121         #
    Asserted                             1         4         3        11         4         9         2       121         #
  Score                               76.9      72.7      95.9      33.9      88.4      28.9      59.5     100.0         %

Units:
  f/a: total count of failed tests [ / count of tests failed with assertion ],
       less is better (0 is ideal);
  #:   count;
  %:   percentage (% of passed tests), more is better.

Т.е. с 40% мы продвинулись до 76% и занимаем третье место после DO и L2S. Работы по улучшению поддержки ведутся. С DO скорее всего созтязаться смысла нет, т.к. там комплексные тесты заточены в основном на тяжёлые ORM, но может и это сделаем.

Что касается скорости linq (вторая таблица), то хотя BLT и на первом месте, но некоторые идеи по улучшению производительности есть. Мы их, кстати, в этом топике коснулись.
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 04.01.10 18:28
Оценка: 8 (1)
Здравствуйте, mrTwister, Вы писали:

IT>>Тогда время на инициализацию и получение мапперов можно свести практически в абсолютный ноль.

T>Вообще, идея очень интересная, но к сожалению в случае с EM неприменима, так как для одних и тех же типов могут существовать разные конфигурации мэпперов.

Сделать хотя бы для дефолтных мапперов. Судя по опыту они используются в 99% случаев.

T>Каждая из стратегий имеет свои достоинства и недостатки, соответственно исходить надо из задачи. Задача Object2Object mapping — это задача с очень смутными и неопределенными вариантами использования из-за того, что их очень много.


Именно поэтому легче делать маппинг object to object вручную.

T>Ведь сопоставление полей объектов можно выполнять кучей разных способов: можно основываться на именах и при этом либо учитывать регистр, или нет, учитывать префиксы типа "m_", "_" или нет, можно основываться на атрибутах (но этот метод не всегда применим и весьма негибок), можно основываться на специальных XML схемах — на чем угодно, на что может хватить фантазии разработчика (я уже не говорю о более сложных задачах типа преобразования типов, коллекций, дженериков, пост/пре обработки и т.д.).


Опять же фантазии в 99% случаев хватает только на атрибуты и XML схему. А в Java так вообще только на последнее.

T>Трезво оценивая свои возможности я понял, что не смогу в приемлимые сроки спроектировать и реализовать интерфейс таким образом, чтобы он покрыл все эти варианты использования, а также те, о которых я ещё не подумал. Вместо этого появилась идея разработать библиотеку, которая с минимальными усилиями позволяет разработчику самому реализовать те варианты ипользования, которые ему нужны, причем именно так, как он себе и представляет идеальным образом. Обрати внимание, что когда был надан вопрос на счет атрибутов мне было не лень продемонстрировать всего несколько строчек кода, реализующие мэппинг через атрибуты. Собственно для этого библиотека и создавалась.


Нужно было не лениться, а продемонстрировать. А ещё лучше, чтобы основные сценарии были в библиотеке по умполчанию. Либо умолчания настраивались для всего приложения, а не для каждого сценария.

IT>>Как раз как маппер, в реальных сценариях BLT даст фору кому угодно.

T>Смотря на каких сценариях. Если это сценарии связанные с БД, то скорее всего да, ведь он именно на эти сценарии и заточен. Если же рассматривать сценарии Object2Object, то уже вряд ли, так как БЛТ сильно уступает конкурентам по функционалу и количеству покрываемых вариантов использования.

Как я уже сказал, проблема в том, что при уж очень заумных сценариях object to object проще написать ручками. Но в принципе, я не возражаю. Возможностей меньше. Хотя больше пока никому не было нужно.

IT>>"Даже вложенные объекты" в BLT не поддерживаются по-умолчанию. Кстати, они не поддерживаются по-умолчанию практически нигде,

T>Ну почему же, AutoMapper поддерживает, и многие другие Object2Object mapping библиотеки поддерживают. Я бы даже сказал, что большинство из них.

А сколько их всего O2O? Я знаю, что подавляющее большинство ORM требуют ручной разметки маппинга для каждого поля, не то, что для вложенных.

IT>>т.к. это вызывает больше проблем, чем бенефитов.

T>Все проблемы решаемы.

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

IT>>Научить BLT справляться с поставленной задачкой можно, например, следующим образом:


T>Ну, это уже "закат солнца вручную". Если уж нет автоматики, не проще ли тогда вообще написать:


Проще. Поверь мне в сценариях O2O проще. Автоматика может привести к большим проблемам как я уже сказал. Да и автоматику на всё не сделаешь. Обычно маппинг во вложенные объекты нужно делать из плоских стркутур. Поле BillingAddressCity в BillingAddress.City. И всё, уже пошёл закат солнца.

T>
T>Destination.i.str2 = Source.i.str2;
T>

T>Тут по крайней мере и интеллисенс есть и компилятор ошибки проверит.

Во! А я о чём?

IT>>Думаю, любому взрослому и умному человеку, заинтересованному в конечном результате, обязательно захотелось бы найти объснению такому чудовищному отставанию в производительности и разобраться что же происходит на самом деле,

T>Ну это очевидно, я же выше по теме написал из-за чего разница в производительности.

Так она же реально не в 250 раз. К тому же ты маппил в один и тот же объект, а BLT создавал каждый раз новые. Одно это уже сокращает разницу в два раза.

IT>>а не отмазываться фразами вроде "Дак это проблемы BLT. Он другого интерфейса не предоставляет.". Тем более, что и интерфейс такой у BLT есть

T>Как это есть? Ты же сам пишешь, что:
T>

API для получения мэппера как это происходит в сценарии в BLT попросту отсутствует.


Я говорю о маппинге в один и тот же объект.

T>А зачем их ставить в одинаковые условия? Это примерно как при сравнении производительности бейсика и С++ код на С++ интерпретировать дабы поставить их в одинаковые условия и тем самым доказать, что бейсик не медленее С++.


Не надо передёргивать. Тестирование в одинаковых условиях нужно для того, чтобы увидеть реальную разницу и понять проблемы. Тестирование в подогнанных под один инструмент условиях (как, например, на ORMBattle) нужно для того, чтобы показать кто круче. Чувствуешь разницу?

Твой тест достаточно переписать вот так:

static long EmitMapper_Simple(int mappingsCount)
{
    var s = new B2();
    var d = new A2();

    var sw = new Stopwatch();
    sw.Start();

    for (int i = 0; i < mappingsCount; ++i)
    {
        var mapper = ObjectsMapperManager.DefaultInstance.GetMapper<B2, A2>(
            new DefaultMapConfig().NullSubstitution<decimal?,int>( state => 42 ));
        d = mapper.Map(s);
    }

    sw.Stop();
    return sw.ElapsedMilliseconds;
}

И разница станет уже в 5 раз, а не в 250. В реальности он именно так использоваться и будет. А со списками мы уже разобрались. EM позволяет получить маппер вне операции маппинга, согласен, это не плохая фишка. Может быть когда-нибудь и в BLT такая появится, но пока никто не просил, что говорит о ненадобности.

T>EmitMapper проектировался в первую очередь как Object2Object mapper. В этом случае схемы данных источников и получателей известны заранее и нет проблемы с тем, чтобы создать конфигурацию мэппера под конкретные схемы данных заранее (например при старте программы) и затем её только использовать.


Это я понял. С другой стороны ты утвержаешь следующее:

2) Очень гибкая. Проецировать можно что угодно на что угодно. Например, датаридер на объекты, объекты на SQL команды (UPDATE, INSERT), объекты на строку (сериализация), строку на объекты (десериализация) и так далее.


IT>>Сценариев где нужен маппинг одного объектв в другой не так много, высокопроизводительных сценариев ещё меньше, а когда они реально возникают, то написать код вручную, особенно сегодня при наличии инициализаторов в C# не представляет особой сложности.


T>Написать код не проблема, проблема его поддерживать. Как показывает практика, достаточно большое количество багов возникает из-за того, что при добавлении нового поля забываем прописать копирование этого поля в одном из существующих ручных мэпперов.


Это правда. Но в конце концов существуют практики повторного использования кода. Да и добавление нового поля может потребовать подстройки маппера. Так что как раз на практике не всё так страшно.

IT>>Оставшаяся разница объясняется тем, что BLT делает больше проверок в рантайм. Например, если изменить приведённый выше код следующим образом, то EM упадёт:


IT>>
IT>>    public decimal? n5 = null;
IT>>


T>И это очень зря, что БЛТ проглотил данную явно ошибочную ситуацию. Что он поставит вместо null? 0? А почему не -1 или не 42?


Это не ошибочная, а самая обычная штатная ситуация. Маппинг long -> int можно было бы назвать ошибочной ситуацией. А с нулевыми значениями всё просто. От источников данных с неизвестной в компайл-тайм стркутурой может приехать всё, что угодно. Даже вот из такай таблицы:

CREATE TABLE MyTable
(
    Field1 int NOT NULL PRIMARY KEY,
    Field2 int NOT NULL
)

можно легко получить NULL в NOT NULL поле:

SELECT Field1, Field2
FROM MyTable WHERE ...
UNION ALL
SELECT NULL, Field2
FROM MyTable WHERE ...

Можно в XML пустую строчку в поле получить, можно в одном объекте поле получить, а в следующем нет, и т.п.

В общем, такая ситуация для BLT самая штатная. И по идее ошибкой является решение её не обрабатывать по умолчанию. Хотя для O2O может и сойдёт. Что поставить вместо null, конечно же, вопрос и его надо решать.

T>EM поддерживает NullSubstitution и с помощью следующей конфигурации можно создать мэппер, который вместо null будет писать 42:

T>
T>var mapper = ObjectsMapperManager.DefaultInstance.GetMapper<B2, A2>(
T>        new DefaultMapConfig().NullSubstitution<decimal?,int>( state => 42 )
T>    );
T>

T>Этот мэппер уже не падает.

Не падает. Только очень многословно получается. Мне это нужно при каждом маппинге выписывать или можно задать где-то одно правило на все варианты использования в программе?

IT>>Некоторые из этих проверок можно сократить только генерацией кода под каждый конкретный вариант использования, что практически не имеет смысла если не кешировать каким-то образом сам вариант использования или явно не напрягать пользователя, что бы он его как-то идентифицировал. В приведённых выше тестах EM именно этим и занимается.


T>К сожалению, без этого нелься сделать сколько-нибудь гибкий мэппер.


Быстрый. Не гибкий, а быстрый. Гибкость в дизайне библиотеки. Там же удобство её использования.

IT>>Это хорошо работает с объектами, но не работает с источниками данных, структура которых становится известной только в момент выполнения. К таким источникам относятся, например, базы данных.


T>Согласен.


IT>>Кстати, давайте посмотрим что у нас с базами данных:

IT>>
IT>>...
IT>>

IT>>В этом примере EM уже начинает отставать.
T>Верно, но после маленькой оптимизации (заменил DbDataReader[String] на DbDataReader[Int]) EM уже начал обгонять BLT.

Я уже хотел было обрадоваться. К сожелению, если написать два теста вот с такими командами:

cmd.CommandText = "SELECT * FROM Customers";        // Test1
cmd.CommandText = "SELECT Phone, * FROM Customers"; // Test2

то после вызова первого теста второй отработает неправильно.

В принципе, такой подход будет работать с линковскми CompiledQuery. Я как раз собираюсь его как-нибудь реализовать на досуге, если будет время.

Кстати, не думал в реализации GetValuesGetter попробовать убрать инициализацию fieldNum через замену делегата на лету. Будет, конечно, дополнительный косвенный вызов, но если кроме fieldNum ещё и тип поля подсмотреть, то можно будет вызывать не reader.GetValue, а, например, reder.GetInt32 и полностью избавиться от боксинга.

IT>>Скорее всего reader.ToObjects, взятый из примеров библиотеки не очень хорош.

T>Во-первых, EM — это не про базы данных. Конфигурация мэппера для дадатидера была показана для примера. Во-вторых, отставание было на считанные проценты на синтетическом примере, при котором вызов "SqlCommand.ExecuteReader" по результатам профилирования составляет всего 4% от общего времени работы программы. В-третьих это уже поправлено

Но как мы видим, нужно продолжать работать.

T>Ничего страшного не случилось бы. Если для кого-то несколько процентов в абсолютной разнице в производительности между DbDataReader[String] и DbDataReader[Int] очень существенны, то, возможно, вместо базы данных следовало бы использовать что-то другое? (потому как судя по всему СУБД простаивает без дела).


Странно такое слышать именно от тебя. С одной стороны ты говоришь о высокой производительности, с другой потеря нескольких процентов фигня. Мне почему-то казалось что из несколько процентов туда-сюда и складывается общая производительность в целом.

IT>>
IT>>public DTOCustomer GetCustomer(Guid customerId)
IT>>{
IT>>    using (var dc = new DataContext())
IT>>    {
IT>>        var customer = dc.Customers.Where(c => c.CustomerID == customerId).Single();
IT>>        return ObjectsMapperManager.DefaultInstance.GetMapper<Customer, DTOCustomer>().Map(customer);
IT>>    }
IT>>}
IT>>


T>А что с ним не так?


Во-первых, многословно. Выписывать столько кода... Я бы предпочёл такую обёртку:

Map.Object2Object<Customer,DTOCustomer>(customer);

или даже

Map.To<DTOCustomer>.From(customer);

Во-вторых, в данном примере происходит двойной маппинг, что уже настолько сажает быстродействие, что о нём можно больше не говорить.
В-третих, твои пользователи первым делом засунут сюда анонимные типы, а с ними EM как я понял не работает совсем.
Если нам не помогут, то мы тоже никого не пощадим.
Re: [ANN] Emit Mapper
От: Holms США  
Дата: 18.11.09 21:35
Оценка: 6 (1)
Здравствуйте, mrTwister, Вы писали:

T>http://emitmapper.codeplex.com


T>Emit Mapper — это мощная легковесная библиотека для проецирования одних объектов на другие. Имеет следующие особенности:


Всё понравилось, кроме того как вы сделали Ignoring members
имхо писать имена как простая строка это плохой моветон.
Я бы добавил ещё атрибуты для полей которые не надо копировать.


var a = ObjectsMapperManager.DefaultInstance.GetMapper<B, A>(
        new DefaultMapConfig().IgnoreMembers<B, A>(new[]{"str1"})
    ).Map(new B());


Кстати, под Silverlight работает? Если нет, опять большой минус.
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[2]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 07.05.10 07:35
Оценка: 4 (1)
Здравствуйте, cadet354, Вы писали:

C>насколько эта библиотека потокобезопасна?

C>например такой подход
C>
C>private static readonly ObjectsMapper<ActivationCodeRequest, SoldLicense> requestToLicense =
C>            ObjectMapperManager.DefaultInstance.GetMapper<ActivationCodeRequest, SoldLicense>();
C>            // и потом где-то в методах
C>            public SoldLicense GetLicense(ActivationCodeRequest request)
C>            {
C>              // код поскипан
C>              SoldLicense license=requestToLicense.Map(request);
C>              // код поскипан
C>              return license;
C>            }
C>

C>жизнеспособен?

Да, жизнеспособен. Сгенерированные мапперы потокобезопасны и lock-free.
лэт ми спик фром май харт
Re[3]: [ANN] Emit Mapper
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 19.11.09 02:49
Оценка: +1
Здравствуйте, mrTwister, Вы писали:

T>Только это разные вещи. Emit Mapper — это библиотека, которую можно использовать для разработки своего собственного BLToolkit с учетом своих собственных требований и пожеланий. Примеры меппинга для DbDataReader и DbCommand приведены исключительно для демонстрации возможностей.


Вообще-то БЛТ в первую очередь маппер, а у же потом всё остальное. Вот автор увидит топик и расскажет подробнее
[КУ] оккупировала армия.
Re[4]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 19.11.09 06:48
Оценка: :)
Здравствуйте, koandrew, Вы писали:

K>Вообще-то БЛТ в первую очередь маппер, а у же потом всё остальное. Вот автор увидит топик и расскажет подробнее



Как раз как маппер, БЛТ довольно слабый (ценность БЛТ не в маппере). Он не поддерживает даже вложенные объекты, не конфигурируется и т.д. По крайней мере не справился даже с такой простой задачкой:

public class Destination
{
    public class Int
    {
        public string str2;
    }

    public string str1;
    public Int i;
}

public class Source
{
    public class Int
    {
        public string str2 = "B1::Int::str2";
    }

    public string str1 = "B1::str1";
    public Int i = new Int();
}


Да и производительность у БЛТ маппера оставляет желать лучшего. На простеньком тесте (класс без вложеных объектов) БЛТ оказался в 250 раз медленнее. Вот код теста:

public class A2
{
    public string str1;
    public string str2;
    public string str3;
    public string str4;
    public string str5;
    public string str6;
    public string str7;
    public string str8;
    public string str9;

    public int n1;
    public int n2;
    public int n3;
    public int n4;
    public int n5;
    public int n6;
    public int n7;
}

public class B2
{
    public string str1 = "str1";
    public string str2 = "str2";
    public string str3 = "str3";
    public string str4 = "str4";
    public string str5 = "str5";
    public string str6 = "str6";
    public string str7 = "str7";
    public string str8 = "str8";
    public string str9 = "str9";

    public int n1 = 1;
    public long n2 = 2;
    public short n3 = 3;
    public byte n4 = 4;
    public decimal n5 = 5;
    public float n6 = 6;
    public int n7 = 7;

}

static long BenchBLToolkit_Simple(int mappingsCount)
{
    var s = new B2();
    var d = new A2();

    d = BLToolkit.Mapping.Map.ObjectToObject<A2>(s);

    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < mappingsCount; ++i)
    {
        d = BLToolkit.Mapping.Map.ObjectToObject<A2>(s);
    }
    sw.Stop();
    return sw.ElapsedMilliseconds;
}

static long EmitMapper_Simple(int mappingsCount)
{
    var mapper = ObjectsMapperManager.DefaultInstance.GetMapper<B2, A2>();
    var s = new B2();
    var d = new A2();

    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < mappingsCount; ++i)
    {
        mapper.Map(s, d);
    }
    sw.Stop();
    return sw.ElapsedMilliseconds;
}


Результаты:

Emit Mapper (simple): 130 milliseconds
BLToolkit (simple): 32287 milliseconds
лэт ми спик фром май харт
Re[2]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 04.01.10 10:31
Оценка: +1
Здравствуйте, IT, Вы писали:

IT>Совсем не плохо.

Спасибо!

IT>Там где можно дженерик методы можно было бы переписать следующим образом:

IT>
IT>static class MapperImpl<TFrom,TTo>
IT>{
IT>    public static ObjectsMapper<TFrom,TTo> Instance = new ObjectsMapper<TFrom, TTo>(
IT>        new ObjectsMapperManager().GetMapperImpl(
IT>            typeof(TFrom),
IT>            typeof(TTo),
IT>            DefaultMapConfig.Instance
IT>        )
IT>    );
IT>}
IT>public ObjectsMapper<TFrom, TTo> GetMapper<TFrom, TTo>()
IT>{
IT>    return MapperImpl<TFrom,TTo>.Instance;
IT>}
IT>

IT>Тогда время на инициализацию и получение мапперов можно свести практически в абсолютный ноль.


Вообще, идея очень интересная, но к сожалению в случае с EM неприменима, так как для одних и тех же типов могут существовать разные конфигурации мэпперов.

IT>Этот подход ведёт в никуда. Пользователям нужна готовая функциональность, а не потенциальная возможность. Это я как собаковод говорю. "ничто не мешает реализовать" в 99.99% случаев означает, что никто ничего реализовывать никогда и не будет. Более того, разработчик инструмента должен держать своё мнение о моветонах при себе. Учить пользователей жизни — это не его работа. Нормальное объяснение отсутсвия какой-либо функциональности в инструменте это: лень, нет времени, технические проблемы, отсутствие выгоды и т.п.


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

1) Стратегия "Рыба". Предугадать возможные варианты использования и реализовать под них готовую функциональность. (это как раз то, о чем ты говоришь)
2) Стратегия "Удочка". Предоставив пользователю интерфейс с помощью которого он может самостоятельно добиться желаемого результата. Тем самым автоматически покрывается большинство вариантов использования и даже те из них, о существовании которых автор библиотеки даже не подозревает.

Каждая из стратегий имеет свои достоинства и недостатки, соответственно исходить надо из задачи. Задача Object2Object mapping — это задача с очень смутными и неопределенными вариантами использования из-за того, что их очень много. Ведь сопоставление полей объектов можно выполнять кучей разных способов: можно основываться на именах и при этом либо учитывать регистр, или нет, учитывать префиксы типа "m_", "_" или нет, можно основываться на атрибутах (но этот метод не всегда применим и весьма негибок), можно основываться на специальных XML схемах — на чем угодно, на что может хватить фантазии разработчика (я уже не говорю о более сложных задачах типа преобразования типов, коллекций, дженериков, пост/пре обработки и т.д.). Трезво оценивая свои возможности я понял, что не смогу в приемлимые сроки спроектировать и реализовать интерфейс таким образом, чтобы он покрыл все эти варианты использования, а также те, о которых я ещё не подумал. Вместо этого появилась идея разработать библиотеку, которая с минимальными усилиями позволяет разработчику самому реализовать те варианты ипользования, которые ему нужны, причем именно так, как он себе и представляет идеальным образом. Обрати внимание, что когда был надан вопрос на счет атрибутов мне было не лень продемонстрировать всего несколько строчек кода, реализующие мэппинг через атрибуты. Собственно для этого библиотека и создавалась.

IT>Как раз как маппер, в реальных сценариях BLT даст фору кому угодно.

Смотря на каких сценариях. Если это сценарии связанные с БД, то скорее всего да, ведь он именно на эти сценарии и заточен. Если же рассматривать сценарии Object2Object, то уже вряд ли, так как БЛТ сильно уступает конкурентам по функционалу и количеству покрываемых вариантов использования.

IT>"Даже вложенные объекты" в BLT не поддерживаются по-умолчанию. Кстати, они не поддерживаются по-умолчанию практически нигде,

Ну почему же, AutoMapper поддерживает, и многие другие Object2Object mapping библиотеки поддерживают. Я бы даже сказал, что большинство из них.

IT>т.к. это вызывает больше проблем, чем бенефитов.

Все проблемы решаемы.

IT>Научить BLT справляться с поставленной задачкой можно, например, следующим образом:


IT>
IT>[MapField("str2", "i.str2")]
IT>public class Destination
IT>{
IT>    public class Int
IT>    {
IT>        public string str2;
IT>    }

IT>    public string str1;
IT>    public Int i = new Int();
IT>}

IT>[MapField("str2", "i.str2")]
IT>public class Source
IT>{
IT>    public class Int
IT>    {
IT>        public string str2 = "B1::Int::str2";
IT>    }

IT>    public string str1 = "B1::str1";
IT>    public Int i = new Int();
IT>}
IT>


Ну, это уже "закат солнца вручную". Если уж нет автоматики, не проще ли тогда вообще написать:
Destination.i.str2 = Source.i.str2;

Тут по крайней мере и интеллисенс есть и компилятор ошибки проверит.

IT>Думаю, любому взрослому и умному человеку, заинтересованному в конечном результате, обязательно захотелось бы найти объснению такому чудовищному отставанию в производительности и разобраться что же происходит на самом деле,

Ну это очевидно, я же выше по теме написал из-за чего разница в производительности.

IT>а не отмазываться фразами вроде "Дак это проблемы BLT. Он другого интерфейса не предоставляет.". Тем более, что и интерфейс такой у BLT есть

Как это есть? Ты же сам пишешь, что:

API для получения мэппера как это происходит в сценарии в BLT попросту отсутствует.


IT>и у EM есть интерфейс, который поставил бы библиотеки в одинаковые условия. И тогда 250 раз мгновенно уменьшились бы на 125. Хотя проблема, конечно, не в этом.


А зачем их ставить в одинаковые условия? Это примерно как при сравнении производительности бейсика и С++ код на С++ интерпретировать дабы поставить их в одинаковые условия и тем самым доказать, что бейсик не медленее С++.

EmitMapper проектировался в первую очередь как Object2Object mapper. В этом случае схемы данных источников и получателей известны заранее и нет проблемы с тем, чтобы создать конфигурацию мэппера под конкретные схемы данных заранее (например при старте программы) и затем её только использовать. Посмотри выше по теме здесь
Автор:
Дата: 30.12.09
- человек именно так и делает.

IT>Сценариев где нужен маппинг одного объектв в другой не так много, высокопроизводительных сценариев ещё меньше, а когда они реально возникают, то написать код вручную, особенно сегодня при наличии инициализаторов в C# не представляет особой сложности.


Написать код не проблема, проблема его поддерживать. Как показывает практика, достаточно большое количество багов возникает из-за того, что при добавлении нового поля забываем прописать копирование этого поля в одном из существующих ручных мэпперов.

IT>В общем, BLT под такие сценарии никогда не оптимизировался. Другое дело вот такие сценарии:


IT>
IT>...
IT>

IT>Здесь мы уже имеем разницу не в 250 раз, а около двух, хотя и не в пользу BLT.
У меня получается разница в 4-5 раз. Ну да неважно, это уже более-менее сравнимо.

IT>Оставшаяся разница объясняется тем, что BLT делает больше проверок в рантайм. Например, если изменить приведённый выше код следующим образом, то EM упадёт:


IT>
IT>public class B2
IT>{
IT>    ...
IT>    public decimal? n5 = null;
IT>    ....
IT>}
IT>


И это очень зря, что БЛТ проглотил данную явно ошибочную ситуацию. Что он поставит вместо null? 0? А почему не -1 или не 42?
EM поддерживает NullSubstitution и с помощью следующей конфигурации можно создать мэппер, который вместо null будет писать 42:
var mapper = ObjectsMapperManager.DefaultInstance.GetMapper<B2, A2>(
        new DefaultMapConfig().NullSubstitution<decimal?,int>( state => 42 )
    );

Этот мэппер уже не падает.

IT>Некоторые из этих проверок можно сократить только генерацией кода под каждый конкретный вариант использования, что практически не имеет смысла если не кешировать каким-то образом сам вариант использования или явно не напрягать пользователя, что бы он его как-то идентифицировал. В приведённых выше тестах EM именно этим и занимается.


К сожалению, без этого нелься сделать сколько-нибудь гибкий мэппер.

IT>Это хорошо работает с объектами, но не работает с источниками данных, структура которых становится известной только в момент выполнения. К таким источникам относятся, например, базы данных.


Согласен.

IT>Кстати, давайте посмотрим что у нас с базами данных:

IT>
IT>...
IT>

IT>В этом примере EM уже начинает отставать.
Верно, но после маленькой оптимизации (заменил DbDataReader[String] на DbDataReader[Int]) EM уже начал обгонять BLT.

IT>Скорее всего reader.ToObjects, взятый из примеров библиотеки не очень хорош.

Во-первых, EM — это не про базы данных. Конфигурация мэппера для дадатидера была показана для примера. Во-вторых, отставание было на считанные проценты на синтетическом примере, при котором вызов "SqlCommand.ExecuteReader" по результатам профилирования составляет всего 4% от общего времени работы программы. В-третьих это уже поправлено

IT>При этом он не очень хорош будучи написанным самим автором библиотеки, а что будет написано, если будет, пользователями, плохо знакомыми как с самой библиотекой, так и с базами данных?


Ничего страшного не случилось бы. Если для кого-то несколько процентов в абсолютной разнице в производительности между DbDataReader[String] и DbDataReader[Int] очень существенны, то, возможно, вместо базы данных следовало бы использовать что-то другое? (потому как судя по всему СУБД простаивает без дела).

IT>Ну и в заключении, вот такие примеры в качестве сценарии использования библиотеки из документации лучше убрать:


IT>
IT>public DTOCustomer GetCustomer(Guid customerId)
IT>{
IT>    using (var dc = new DataContext())
IT>    {
IT>        var customer = dc.Customers.Where(c => c.CustomerID == customerId).Single();
IT>        return ObjectsMapperManager.DefaultInstance.GetMapper<Customer, DTOCustomer>().Map(customer);
IT>    }
IT>}
IT>


А что с ним не так?

IT>И в самом самом заключении, ObjectsMapperManager — это немного не по-английски.

Ок
лэт ми спик фром май харт
Re[13]: [ANN] Emit Mapper
От: Mr.Cat  
Дата: 07.05.10 07:50
Оценка: +1
Здравствуйте, mrTwister, Вы писали:
T>К сожалению, я ошибся, в текущей версии это не сделать Не хватает метода расширения, чтобы можно было получить объект после того, как он был создан, но до того, как началось копирование его свойств.
Или возможности вызвать копирования свойств из кастомного ConvertUsing.
Re[2]: [ANN] Emit Mapper
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 09.09.10 23:40
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>как с помощью Emit Mapper замапить поля на созданный экземпляр класса Person?


Такое умеет дефолтный xml-(де)сериализатор XmlSerializer
[КУ] оккупировала армия.
Re[2]: [ANN] Emit Mapper
От: Tom Россия http://www.RSDN.ru
Дата: 18.11.09 21:53
Оценка:
H>Всё понравилось, кроме того как вы сделали Ignoring members
А в каких случаях это вообще надо использовать? Почему просто не генерить C# код?
Народная мудрось
всем все никому ничего(с).
Re[3]: [ANN] Emit Mapper
От: Holms США  
Дата: 18.11.09 22:14
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>А в каких случаях это вообще надо использовать? Почему просто не генерить C# код?

В случаях когда мне не надо что-бы значение из определёного свойства копировалось в другой обьект.
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[2]: [ANN] Emit Mapper
От: Holms США  
Дата: 18.11.09 22:14
Оценка:
Здравствуйте, koandrew, Вы писали:


K>Бегло просмотрел. Вывод — BLToolkit круче


А как с подержкой Silverlight-a в BLToolkit-e?
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[2]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 18.11.09 22:16
Оценка:
Здравствуйте, koandrew, Вы писали:

K>Бегло просмотрел. Вывод — BLToolkit круче


Только это разные вещи. Emit Mapper — это библиотека, которую можно использовать для разработки своего собственного BLToolkit с учетом своих собственных требований и пожеланий. Примеры меппинга для DbDataReader и DbCommand приведены исключительно для демонстрации возможностей.
лэт ми спик фром май харт
Re[3]: [ANN] Emit Mapper
От: Holms США  
Дата: 18.11.09 22:17
Оценка:
Здравствуйте, mrTwister, Вы писали:


T>Имхо, заставлять вешать атрибуты — это еще больший моветон. Это примерно как заставлять наследоваться от специального класса. Тем более, что ничто не мешает реализовать требуемую функциональность своими силами на основе Emit Mapper. Самый простой путь — это тупо отнаследоваться от DefaultMapConfig и переопределить логику игнора с учетом своих собственных требований и пожеланий (это могут быть не только атрибуты):


ага ясно, ну тогда хорошо.
еще-бы подержку Silverlight-а добавили и было бы всё пучком
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[3]: [ANN] Emit Mapper
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 19.11.09 00:17
Оценка:
Здравствуйте, Holms, Вы писали:

H>А как с подержкой Silverlight-a в BLToolkit-e?


Всё будет
[КУ] оккупировала армия.
Re[4]: [ANN] Emit Mapper
От: Holms США  
Дата: 19.11.09 01:13
Оценка:
Здравствуйте, koandrew, Вы писали:


K>Всё будет

то что будет для SL + LINQ + code generation tool никто не сомневается, мне щас надо, поэтому остановился пока на SubSonic (осбенно мне нравится генериция ДБ обьектов из моих C# классов).
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[5]: [ANN] Emit Mapper
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 19.11.09 01:17
Оценка:
Здравствуйте, Holms, Вы писали:

H>то что будет для SL + LINQ

Над этим работают
H>+ code generation tool
Вряд ли будет, ибо свой тул с таким функционалом пишется за полчаса-час.
[КУ] оккупировала армия.
Re[2]: [ANN] Emit Mapper
От: Andy77 Ниоткуда  
Дата: 19.11.09 02:05
Оценка:
Здравствуйте, koandrew, Вы писали:

K>Бегло просмотрел. Вывод — BLToolkit круче


Круче, конечно. А как там реализовать похожую фичу?
Re[2]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 21.12.09 14:01
Оценка:
Здравствуйте, Holms, Вы писали:


H>
H>var a = ObjectsMapperManager.DefaultInstance.GetMapper<B, A>(
H>        new DefaultMapConfig().IgnoreMembers<B, A>(new[]{"str1"})
H>    ).Map(new B());
H>


H>Кстати, под Silverlight работает? Если нет, опять большой минус.


Теперь работает

P.S.: Выражаю огромное спасибо Holms за участие в портировании библиотеки на Silverlight!
лэт ми спик фром май харт
Re: [ANN] Emit Mapper
От: Аноним  
Дата: 30.12.09 08:57
Оценка:
Здравствуйте, mrTwister

Я хотел бы использовать EmitMapper для клонирования объектов.

Имею следующий объект, с вложенной коллекцией OrgNodeCollection :
    [Serializable]
    [XmlRoot(ElementName = "object")]
    public class OrgNode
    {
        [XmlIgnore]
        public OrgNode ParentNode { get; set; }

        #region XmlAttributes

        [XmlAttribute("otype")]
        public string Type { get; set; }

        [XmlAttribute("id")]
        public string Id { get; set; }

        [XmlAttribute("prel")]
        public string ParentRelation { get; set; }

        [XmlAttribute("alias")]
        public string Alias { get; set; }

        #endregion

        #region XmlTags

        [XmlElement("description")]
        public string Description { get; set; }

        #endregion

        private OrgNodeCollection _children;

        public OrgNode()
        {
            Children = new OrgNodeCollection();
        }

        [XmlArray("children")]
        [XmlArrayItem("object")]
        public OrgNodeCollection Children
        {
            get { return _children; }
            set { _children = value; _children.Parent = this; }
        }
    }
    
    [Serializable]
    public class OrgNodeCollection : List<OrgNode>
    {
        private OrgNode _parent;

        public OrgNode Parent
        {
            get { return _parent; }
            set
            {
                _parent = value;
                foreach (var collection in this)
                {
                    collection.ParentNode = Parent;
                }
            }
        }

        public new void Add(OrgNode item)
        {
            base.Add(item);
            item.ParentNode = Parent;
        }
    }


Маппер использую вот так:

private static readonly Mapper<OrgNode, OrgNode> Mapper = ObjectsMapperManager.DefaultInstance.GetMapper<OrgNode, OrgNode>(new DefaultMapConfig().DeepMap<OrgNode>());

_savedObject = Mapper.Map<OrgNode, OrgNode>(node);


далее когда выполняю:

_savedObject.Children.Clear();


коллекция Children становится пустой и у _savedObject и у node. Соответственно коллекция Children одна та же.

Как заставить это работать?
Re[5]: [ANN] Emit Mapper
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.12.09 19:26
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Да и производительность у БЛТ маппера оставляет желать лучшего. На простеньком тесте (класс без вложеных объектов) БЛТ оказался в 250 раз медленнее. Вот код теста:


А ты не задумывался о том, что у BLT может быть ленивая генерация кода?
... << RSDN@Home 1.2.0 alpha 4 rev. 1324 on Windows 7 6.1.7600.0>>
AVK Blog
Re[2]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 30.12.09 19:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, mrTwister


А>Я хотел бы использовать EmitMapper для клонирования объектов.

А>Маппер использую вот так:

А>
А>private static readonly Mapper<OrgNode, OrgNode> Mapper = ObjectsMapperManager.DefaultInstance.GetMapper<OrgNode, OrgNode>(new DefaultMapConfig().DeepMap<OrgNode>());

А>_savedObject = Mapper.Map<OrgNode, OrgNode>(node);
А>


А>далее когда выполняю:


А>
А>_savedObject.Children.Clear();
А>


А>коллекция Children становится пустой и у _savedObject и у node. Соответственно коллекция Children одна та же.


А>Как заставить это работать?


Нужно создавать маппер следующим образом:

private static readonly Mapper<OrgNode, OrgNode> Mapper = 
    ObjectsMapperManager.DefaultInstance.GetMapper<OrgNode, OrgNode>(new DefaultMapConfig().DeepMap());
лэт ми спик фром май харт
Re[6]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 30.12.09 19:44
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>А ты не задумывался о том, что у BLT может быть ленивая генерация кода?


Задумывался. Именно по-этому в тесте есть строчка (выделено жирным):

static long BenchBLToolkit_Simple(int mappingsCount)
{
    var s = new B2();
    var d = new A2();

    d = BLToolkit.Mapping.Map.ObjectToObject<A2>(s);

    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < mappingsCount; ++i)
    {
        d = BLToolkit.Mapping.Map.ObjectToObject<A2>(s);
    }
    sw.Stop();
    return sw.ElapsedMilliseconds;
}
лэт ми спик фром май харт
Re[7]: [ANN] Emit Mapper
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.12.09 23:09
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Задумывался. Именно по-этому в тесте есть строчка (выделено жирным):


Что то у тебя явно не то.
... << RSDN@Home 1.2.0 alpha 4 rev. 1324 on Windows 7 6.1.7600.0>>
AVK Blog
Re[8]: [ANN] Emit Mapper
От: WolfHound  
Дата: 31.12.09 09:30
Оценка:
Здравствуйте, AndrewVK, Вы писали:

T>>Задумывался. Именно по-этому в тесте есть строчка (выделено жирным):

Так очевидно что именно...

d = BLToolkit.Mapping.Map.ObjectToObject<A2>(s);

mapper.Map(s, d);

BLT каждый раз создает новый объект. EM тупо копирует в один и тотже не напрягая GC.
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[9]: [ANN] Emit Mapper
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 31.12.09 09:33
Оценка:
Здравствуйте, WolfHound, Вы писали:

T>>>Задумывался. Именно по-этому в тесте есть строчка (выделено жирным):

WH>Так очевидно что именно...

WH>d = BLToolkit.Mapping.Map.ObjectToObject<A2>(s);


WH>mapper.Map(s, d);


WH>BLT каждый раз создает новый объект. EM тупо копирует в один и тотже не напрягая GC.


Ясно. Что то подобное я и предполагал.
... << RSDN@Home 1.2.0 alpha 4 rev. 1324 on Windows 7 6.1.7600.0>>
AVK Blog
Re[9]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 31.12.09 12:03
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Так очевидно что именно...


WH>d = BLToolkit.Mapping.Map.ObjectToObject<A2>(s);


WH>mapper.Map(s, d);


WH>BLT каждый раз создает новый объект. EM тупо копирует в один и тотже не напрягая GC.


Дак это проблемы BLT. Он другого интерфейса не предоставляет.
Плюс к этому BLT при конвертации value типов делает боксинг/анбоксинг. EM обходится без этого.
лэт ми спик фром май харт
Re[10]: [ANN] Emit Mapper
От: WolfHound  
Дата: 31.12.09 15:12
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Дак это проблемы BLT. Он другого интерфейса не предоставляет.

T>Плюс к этому BLT при конвертации value типов делает боксинг/анбоксинг. EM обходится без этого.
Лично я вижу только одно объяснение этому: Данные сценарии за все время существования BLT ни кому ни разу не понадобились.
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 03.01.10 06:35
Оценка:
Здравствуйте, Holms, Вы писали:

H>пост не в тему, но

H>последняя версия BL из svn не компилится, можете поправить
H>вот пара ошибок

Только что пересобрал в обоих фреймворках. Компилируется нормально. Может какие-то проблемы с локальной версией?

H>Кстати, какие планы насчет Silverlight-а. Будет поддержка?


Сделаем. Технических проблем пока вроде не видно.
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: [ANN] Emit Mapper
От: Holms США  
Дата: 03.01.10 06:42
Оценка:
Здравствуйте, IT, Вы писали:

IT>Только что пересобрал в обоих фреймворках. Компилируется нормально. Может какие-то проблемы с локальной версией?

а какие проблемы могут быть? я взял то что в SVN-е потом запустил
%windir%\Microsoft.NET\Framework\v3.5\MSBuild.exe BLToolkit.2008.sln  /property:Configuration=Release

может кое-что не попало в SVN?

IT>Сделаем. Технических проблем пока вроде не видно.

отлично. Any ETA?
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[5]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 03.01.10 06:57
Оценка:
Здравствуйте, Holms, Вы писали:

IT>>Только что пересобрал в обоих фреймворках. Компилируется нормально. Может какие-то проблемы с локальной версией?

H>а какие проблемы могут быть? я взял то что в SVN-е потом запустил
H>
H>%windir%\Microsoft.NET\Framework\v3.5\MSBuild.exe BLToolkit.2008.sln  /property:Configuration=Release
H>

H>может кое-что не попало в SVN?

Current SVN snapshots отсюда собираются путём скачки последней версии в чистый каталог и запуском

%windir%\Microsoft.NET\Framework\v3.5\MSBuild.exe BLToolkit.3.csproj /property:Configuration=Release

Твой вариант я тоже только что проверил, всё работает.

IT>>Сделаем. Технических проблем пока вроде не видно.

H>отлично. Any ETA?

Что нужнее, DML или SL?
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: [ANN] Emit Mapper
От: Holms США  
Дата: 03.01.10 07:10
Оценка:
Здравствуйте, IT, Вы писали:

IT>Current SVN snapshots отсюда собираются путём скачки последней версии в чистый каталог и запуском


IT>
IT>%windir%\Microsoft.NET\Framework\v3.5\MSBuild.exe BLToolkit.3.csproj /property:Configuration=Release
IT>

IT>Твой вариант я тоже только что проверил, всё работает.
я беру отсюда http://bl-toolkit.googlecode.com/svn/trunk
мне выдаёт Revision 864, и файла BLToolkit.3.csproj в руте нету.

что-то здесь не то, и вот что конкретно

если брать откуда я беру то получаем всё что там е тебя есть, и файл BLToolkit.2008.sln не содержит линк на Source/BLToolkit.3.csproj

после запуска Source/Compile3.bat то и BLToolkit.2008.sln собралось без проблем.

IT>Что нужнее, DML или SL?

что скрывается под DML?
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[3]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 03.01.10 16:25
Оценка:
Здравствуйте, Holms, Вы писали:

H>пост не в тему, но

H>последняя версия BL из svn не компилится, можете поправить

Нашёл.
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: [ANN] Emit Mapper
От: Holms США  
Дата: 04.01.10 10:04
Оценка:
Здравствуйте, IT, Вы писали:

IT>Нашёл.

отлично

теперь ждём DML для LINQ-a
большая просьба, не мудрите с этим, сделаете просто как в SubSonic, а не как в Linq2Sql от MS.

Спасибо

Silverlight пока можно пропустить.
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[6]: [ANN] Emit Mapper
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.01.10 12:34
Оценка:
Здравствуйте, IT, Вы писали:

IT>Что нужнее, DML или SL?


DML
... << RSDN@Home 1.2.0 alpha 4 rev. 1331 on Windows 7 6.1.7600.0>>
AVK Blog
Re[3]: [ANN] Emit Mapper
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.01.10 12:34
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>1) Стратегия "Рыба". Предугадать возможные варианты использования и реализовать под них готовую функциональность. (это как раз то, о чем ты говоришь)

T>2) Стратегия "Удочка". Предоставив пользователю интерфейс с помощью которого он может самостоятельно добиться желаемого результата. Тем самым автоматически покрывается большинство вариантов использования и даже те из них, о существовании которых автор библиотеки даже не подозревает.

Правильная стратегия — рыба для публично доступного ядра и удочка для набора функционала вокруг. Именно по такой схеме построен BLT.
... << RSDN@Home 1.2.0 alpha 4 rev. 1331 on Windows 7 6.1.7600.0>>
AVK Blog
Re[4]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 04.01.10 12:51
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Правильная стратегия — рыба для публично доступного ядра и удочка для набора функционала вокруг. Именно по такой схеме построен BLT.


Вопрос только в объеме рыбы и простоте и доступности удочек.
лэт ми спик фром май харт
Re[5]: [ANN] Emit Mapper
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.01.10 14:41
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Вопрос только в объеме рыбы


Ядро у BLT довольно маленькое.

T> и простоте и доступности удочек.


А это вовсе не вопрос, потому что проблемы с конкретной удочкой вполне решаемы написанием собственной удочки в крайнем случае.
... << RSDN@Home 1.2.0 alpha 4 rev. 1333 on Windows 7 6.1.7600.0>>
AVK Blog
Re[7]: [ANN] Emit Mapper
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 04.01.10 15:14
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Прекрасно. Сколько надо написать кода для маппинга вложенных структур (в том числе рекурсивных)?


Это лучше у IT спросить.
... << RSDN@Home 1.2.0 alpha 4 rev. 1333 on Windows 7 6.1.7600.0>>
AVK Blog
Re[5]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 04.01.10 16:20
Оценка:
Здравствуйте, Holms, Вы писали:

H>теперь ждём DML для LINQ-a

H>большая просьба, не мудрите с этим, сделаете просто как в SubSonic, а не как в Linq2Sql от MS.

А как сделано в SubSonic? Можно ссылочку на примеры?
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: [ANN] Emit Mapper
От: Holms США  
Дата: 04.01.10 16:45
Оценка:
Здравствуйте, IT, Вы писали:

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


IT>А как сделано в SubSonic? Можно ссылочку на примеры?

хочется такого что-то в этом роде

1.
Person p;
db.Person.Insert(p = new Person(){...});
Console.WriteLine(p.Id);
2.
db.Update<T>(T p, int pkValue, Func<T, string> pkNameGetter);
здесь так-же хочется что-бы не посылать все поля а только те которые нужны.
3.
db.Delete<T>(int pkValue, Func<T, string> pkNameGetter);

желательно что-бы была возможность всё это дело запихнуть в транзакцию.

В остальном я доволен, вчера попробовал кое-что для себя, сработало отлично

А, я не особо искал, но может где-то внутри BL есть функцинальность для определения сущностей БД, т.е. список таблиц, список столбцов,..., ведь для рахных БД это по разному?

Спасибо

P.S. Перехожу на BL, хотя надо ознакомиться с лицензией
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[7]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 04.01.10 18:45
Оценка:
Здравствуйте, Holms, Вы писали:

H>хочется такого что-то в этом роде


H>1.

H>Person p;
H>db.Person.Insert(p = new Person(){...});
H>Console.WriteLine(p.Id);

Такая функциональность есть см. SqlQuery, только без p.Id. Она делается без линка. Для Insert от линка интересно прежде всего получить следующее:

INSERT INTO (...)
SELECT ... FROM ...


H>2.

H>db.Update<T>(T p, int pkValue, Func<T, string> pkNameGetter);
H>здесь так-же хочется что-бы не посылать все поля а только те которые нужны.

Такое не интересно. Нужна семантика в рамках линка без строковых констант.

H>3.

H>db.Delete<T>(int pkValue, Func<T, string> pkNameGetter);

H>желательно что-бы была возможность всё это дело запихнуть в транзакцию.


Тоже самое, интересен DELETE по условию, а не для одного объекта.

H>А, я не особо искал, но может где-то внутри BL есть функцинальность для определения сущностей БД, т.е. список таблиц, список столбцов,..., ведь для рахных БД это по разному?


Не совсем понял вопроса.

H>P.S. Перехожу на BL, хотя надо ознакомиться с лицензией


MIT. Можешь исходники хоть упаковывать в коробку и продавать.
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: [ANN] Emit Mapper
От: Holms США  
Дата: 04.01.10 19:15
Оценка:
Здравствуйте, IT, Вы писали:

IT>Такое не интересно. Нужна семантика в рамках линка без строковых констант.

IT>Тоже самое, интересен DELETE по условию, а не для одного объекта.

ясно, просто ненавижу как это сделано в Linq2Sql
т.е.

var p = DbContext.Person.Where(_ => _.Id = myIdToDelete);
DbContext.DeleteOnSubmit(p);
DbContext.SubmitChanges();


слишком много кода, также и для Update.
хочется одной строкой

H>>А, я не особо искал, но может где-то внутри BL есть функцинальность для определения сущностей БД, т.е. список таблиц, список столбцов,..., ведь для рахных БД это по разному?


IT>Не совсем понял вопроса.

нужен функционал который бы выдавал список таблиц, список столбцов из таблицы, primary keys, ... который бы работал прозрачно для разных DataProviders.

IT>MIT. Можешь исходники хоть упаковывать в коробку и продавать.

отлично
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[9]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 04.01.10 19:27
Оценка:
Здравствуйте, Holms, Вы писали:

IT>>Не совсем понял вопроса.

H>нужен функционал который бы выдавал список таблиц, список столбцов из таблицы, primary keys, ... который бы работал прозрачно для разных DataProviders.

Такого нет. Но вроде как DataProviders умеют возвращать схему базы и без BLT.
Если нам не помогут, то мы тоже никого не пощадим.
Re[10]: [ANN] Emit Mapper
От: Holms США  
Дата: 04.01.10 19:41
Оценка:
Здравствуйте, IT, Вы писали:

IT>Такого нет. Но вроде как DataProviders умеют возвращать схему базы и без BLT.

так это я знаю
подумалось ведь ты всёравно для разных провайдеров по своему составляешь запросы, может и эта функциональность (db schema info) где-то потребовалась и уже есть, что-бы мне не писать заново велосипед
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[11]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 04.01.10 21:54
Оценка:
Здравствуйте, Holms, Вы писали:

IT>>Такого нет. Но вроде как DataProviders умеют возвращать схему базы и без BLT.

H>так это я знаю
H>подумалось ведь ты всёравно для разных провайдеров по своему составляешь запросы, может и эта функциональность (db schema info) где-то потребовалась и уже есть,

Мне это совсем не нужно. Всё описание содержится в модели данных.

H>что-бы мне не писать заново велосипед


Напиши, если получится что-то всем полезное, но можно будет в BLT добавить.
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 04.01.10 23:34
Оценка:
Здравствуйте, IT, Вы писали:

IT>Сделать хотя бы для дефолтных мапперов. Судя по опыту они используются в 99% случаев.


Мысль здравая

IT>Именно поэтому легче делать маппинг object to object вручную.


Вовсе нет. Ты верно выше отметил, что в 99% случаев работает дефолтная конфигурация. Проще вручную бороться с 1% чем с 100%.

IT>Нужно было не лениться, а продемонстрировать.


Ну дак я и продемонстрировал здесь
Автор: mrTwister
Дата: 19.11.09


IT>А ещё лучше, чтобы основные сценарии были в библиотеке по умполчанию.


Да, наверное ты все-таки прав.

IT>Либо умолчания настраивались для всего приложения, а не для каждого сценария.


А это уже доступно. Есть дефолтный конфигуратор — класс DefaultMapConfig. Этот класс инкапсулирует в себе все правила мэппинга. Ты можешь создать один или несколько глобальных экземпляров этого класса и использовать их когда надо:

public class Program
{
    public static IMappingConfigurator config1;
    public static IMappingConfigurator config2;

    static Program()
    {
        config1 = new DefaultMapConfig()
            .MatchMembers((m1, m2) => m1.ToLower() == m2.ToLower()) // ignore case of field names
            .NullSubstitution<object, int>(state => 42) // all nulls will be int 42
            .SetConfigName("config1");

        config2 = new DefaultMapConfig()
            .NullSubstitution<object, object>(state => DBNull.Value) // all nulls will be DBNull.Value
            .SetConfigName("config2");
    }
...
    public void Foo()
    {
        ...
        var dest = ObjectsMapperManager.DefaultInstance.GetMapper<Source, Destination>(config1).Map(source);
    }
...
}


Кроме того, существует глобальная дефолтная конфигурация, которая используется по-умолчанию. Эта конфигурация доступна через "DefaultMapConfig.Instance" и её так же можно менять и соответственно поведение будет глобально меняться.

DefaultMapConfig.Instance.MatchMembers((m1, m2) => m1.ToLower() == m2.ToLower());
...
dest = ObjectsMapperManager.DefaultInstance.GetMapper<Source, Destination>().Map(source);

IT>Как я уже сказал, проблема в том, что при уж очень заумных сценариях object to object проще написать ручками.

До поры до времени — пока полей в классах не много.

IT>Но в принципе, я не возражаю. Возможностей меньше. Хотя больше пока никому не было нужно.


Потому что при работе с базой оно действительно не особо и надо.

IT>А сколько их всего O2O?


Из популярных — это AutoMapper, Glue, Otis. Есть еще и другие, сходу не вспомню.

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

IT>Проще. Поверь мне в сценариях O2O проще. Автоматика может привести к большим проблемам как я уже сказал.

А подробней про проблемы можно?

IT>Не надо передёргивать. Тестирование в одинаковых условиях нужно для того, чтобы увидеть реальную разницу и понять проблемы. Тестирование в подогнанных под один инструмент условиях (как, например, на ORMBattle) нужно для того, чтобы показать кто круче. Чувствуешь разницу?


Ок, будем считать, что я имел ввиду условия О2О, когда схемы данных известны заранее. В условиях когда схемы данных заранее неизвестны или в условиях DB2O выигрыш уже гораздо меньше. Так нормально?

IT>Это я понял. С другой стороны ты утвержаешь следующее:


IT>

IT>2) Очень гибкая. Проецировать можно что угодно на что угодно. Например, датаридер на объекты, объекты на SQL команды (UPDATE, INSERT), объекты на строку (сериализация), строку на объекты (десериализация) и так далее.


Смысл этой фразы в том, что с помощью ЕМ можно автоматически проецировать что угодно куда угодно, а не то, что ЕМ — это ORM фреймворк. Я на http://emitmapper.codeplex.com прямо так и написал:

Essential point of the source code above is not that it is another one "Super ORM". Essential point is that you can yourself develop very effective and light database access utilities in respect to your project requirements. Sometimes it is more preferable than using some huge generic ORM.


IT>Это правда. Но в конце концов существуют практики повторного использования кода. Да и добавление нового поля может потребовать подстройки маппера. Так что как раз на практике не всё так страшно.


Подстройка маппера требуется очень редко.


T>>EM поддерживает NullSubstitution и с помощью следующей конфигурации можно создать мэппер, который вместо null будет писать 42:

T>>
T>>var mapper = ObjectsMapperManager.DefaultInstance.GetMapper<B2, A2>(
T>>        new DefaultMapConfig().NullSubstitution<decimal?,int>( state => 42 )
T>>    );
T>>

T>>Этот мэппер уже не падает.

IT>Не падает. Только очень многословно получается. Мне это нужно при каждом маппинге выписывать или можно задать где-то одно правило на все варианты использования в программе?


Можно (см выше).

IT>Я уже хотел было обрадоваться. К сожелению, если написать два теста вот с такими командами:


IT>
IT>cmd.CommandText = "SELECT * FROM Customers";        // Test1
IT>cmd.CommandText = "SELECT Phone, * FROM Customers"; // Test2
IT>

IT>то после вызова первого теста второй отработает неправильно.

Ой
Пофиксено.

IT>Кстати, не думал в реализации GetValuesGetter попробовать убрать инициализацию fieldNum через замену делегата на лету. Будет, конечно, дополнительный косвенный вызов, но если кроме fieldNum ещё и тип поля подсмотреть, то можно будет вызывать не reader.GetValue, а, например, reder.GetInt32 и полностью избавиться от боксинга.


Если на лету менять, то боюсь проблемы с многопоточностью будут.

IT>Странно такое слышать именно от тебя. С одной стороны ты говоришь о высокой производительности, с другой потеря нескольких процентов фигня. Мне почему-то казалось что из несколько процентов туда-сюда и складывается общая производительность в целом.


Ладно, согласен, отмазка не прошла.

T>>А что с ним не так?


IT>Во-вторых, в данном примере происходит двойной маппинг, что уже настолько сажает быстродействие, что о нём можно больше не говорить.


А Linq2SQL и EF именно так сейчас чаще всего и используют, они же не поддерживают POCO. Даже статьи на эту тему пишут:http://habrahabr.ru/blogs/net/71820/

IT>В-третих, твои пользователи первым делом засунут сюда анонимные типы, а с ними EM как я понял не работает совсем.

Работает без проблем. Только сборку надо пометить атрибутом
[assembly: InternalsVisibleTo("EmitMapperAssembly")]
лэт ми спик фром май харт
Re[4]: [ANN] Emit Mapper
От: Holms США  
Дата: 05.01.10 06:07
Оценка:
Здравствуйте, IT, Вы писали:

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


H>>пост не в тему, но

H>>последняя версия BL из svn не компилится, можете поправить

Кстати, будешь еще оптимизировать Linq реализацию, а то судя по первой таблице здесь BLToolkit не слишком скоростной.

Хотя кто знает,
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[6]: [ANN] Emit Mapper
От: Holms США  
Дата: 05.01.10 06:40
Оценка:
Здравствуйте, IT, Вы писали:


IT>Что касается скорости linq (вторая таблица), то хотя BLT и на первом месте, но некоторые идеи по улучшению производительности есть. Мы их, кстати, в этом топике коснулись.


Отлично, еще один повод переходить на BL
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
Re[4]: [ANN] Emit Mapper
От: Dog  
Дата: 05.01.10 10:04
Оценка:
T>>Каждая из стратегий имеет свои достоинства и недостатки, соответственно исходить надо из задачи. Задача Object2Object mapping — это задача с очень смутными и неопределенными вариантами использования из-за того, что их очень много.
IT>Именно поэтому легче делать маппинг object to object вручную.
Не надо смутных и неопределённых вариантов. Надо 1 простой для 90% случаев.

IT>>>Как раз как маппер, в реальных сценариях BLT даст фору кому угодно.

T>>Смотря на каких сценариях. Если это сценарии связанные с БД, то скорее всего да, ведь он именно на эти сценарии и заточен. Если же рассматривать сценарии Object2Object, то уже вряд ли, так как БЛТ сильно уступает конкурентам по функционалу и количеству покрываемых вариантов использования.
IT>Как я уже сказал, проблема в том, что при уж очень заумных сценариях object to object проще написать ручками. Но в принципе, я не возражаю. Возможностей меньше. Хотя больше пока никому не было нужно.
Re[2]: Маппинг списков
Автор: Dog
Дата: 18.12.09


T>>Ну, это уже "закат солнца вручную". Если уж нет автоматики, не проще ли тогда вообще написать:

IT>Проще. Поверь мне в сценариях O2O проще. Автоматика может привести к большим проблемам как я уже сказал. Да и автоматику на всё не сделаешь. Обычно маппинг во вложенные объекты нужно делать из плоских стркутур. Поле BillingAddressCity в BillingAddress.City. И всё, уже пошёл закат солнца.
Не надо на всё. Напиши в доке, то-то и то-то не поддерживает. Но чтобы User.Bank.Address в User.Bank.Address или вот
Автор: Dog
Дата: 17.12.09
замапило без приседаний.
Re[5]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 05.01.10 17:33
Оценка:
Здравствуйте, mrTwister, Вы писали:

IT>>Либо умолчания настраивались для всего приложения, а не для каждого сценария.


T>Кроме того, существует глобальная дефолтная конфигурация, которая используется по-умолчанию. Эта конфигурация доступна через "DefaultMapConfig.Instance" и её так же можно менять и соответственно поведение будет глобально меняться.


Кстати, если по религиозным соображениям не хочется делать автоматический маппинг nullable значений в обычные, то для таких конфигураций можно было бы сделать пару методов, которые конфигурировали бы все необходимые типы. По опыту в подавляющем большинстве случаев для замены нулевых значений используются только два значения: 0 или MinValue. Пара методов SetNullToZero и SetNullToMinValue сняли бы большинство вопросов. Плюс неплохо было бы сделать такое конфигурируемым через app.config.

IT>>Проще. Поверь мне в сценариях O2O проще. Автоматика может привести к большим проблемам как я уже сказал.

T>А подробней про проблемы можно?

Например, что делать с circle references, как обрабатывать наследование, кто должен создавать и должен ли экземпляры вложенных объектов, должны ли эти экземпляры копироваться по ссылке или создаваться и маппится по-новой.

На все эти вопросы есть либо ни одного, либо два-три ответа, которые валидны в дефолтной конфигурации.

IT>>Я уже хотел было обрадоваться. К сожелению, если написать два теста вот с такими командами:


IT>>
IT>>cmd.CommandText = "SELECT * FROM Customers";        // Test1
IT>>cmd.CommandText = "SELECT Phone, * FROM Customers"; // Test2
IT>>

IT>>то после вызова первого теста второй отработает неправильно.

T>Ой

T>Пофиксено.

Вижу. Производительность сразу просела. Стало даже медленней чем было по именам.

IT>>Кстати, не думал в реализации GetValuesGetter попробовать убрать инициализацию fieldNum через замену делегата на лету. Будет, конечно, дополнительный косвенный вызов, но если кроме fieldNum ещё и тип поля подсмотреть, то можно будет вызывать не reader.GetValue, а, например, reder.GetInt32 и полностью избавиться от боксинга.


T>Если на лету менять, то боюсь проблемы с многопоточностью будут.


Какие проблемы? Два потока одновременно проинициализируют одно и тоже поле? Так это ерунда.

IT>>Во-вторых, в данном примере происходит двойной маппинг, что уже настолько сажает быстродействие, что о нём можно больше не говорить.

T>А Linq2SQL и EF именно так сейчас чаще всего и используют, они же не поддерживают POCO. Даже статьи на эту тему пишут:http://habrahabr.ru/blogs/net/71820/

Не нашёл где там про это пишут.

IT>>В-третих, твои пользователи первым делом засунут сюда анонимные типы, а с ними EM как я понял не работает совсем.

T>Работает без проблем. Только сборку надо пометить атрибутом
T>[assembly: InternalsVisibleTo("EmitMapperAssembly")]

Нужно тогда диагностику подправить, пользователи замучают вопросами.
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 05.01.10 18:18
Оценка:
Здравствуйте, Dog, Вы писали:

IT>>Именно поэтому легче делать маппинг object to object вручную.

Dog>Не надо смутных и неопределённых вариантов. Надо 1 простой для 90% случаев.

Для 90% случаев нужно строить граф объектов или не нужно?

IT>>Как я уже сказал, проблема в том, что при уж очень заумных сценариях object to object проще написать ручками. Но в принципе, я не возражаю. Возможностей меньше. Хотя больше пока никому не было нужно.

Dog>Re[2]: Маппинг списков
Автор: Dog
Дата: 18.12.09


Что делать в твоём примере, если в A есть обратная ссылка на Foo?

IT>>Проще. Поверь мне в сценариях O2O проще. Автоматика может привести к большим проблемам как я уже сказал. Да и автоматику на всё не сделаешь. Обычно маппинг во вложенные объекты нужно делать из плоских стркутур. Поле BillingAddressCity в BillingAddress.City. И всё, уже пошёл закат солнца.

Dog>Не надо на всё. Напиши в доке, то-то и то-то не поддерживает. Но чтобы User.Bank.Address в User.Bank.Address или вот
Автор: Dog
Дата: 17.12.09
замапило без приседаний.


Можно, конечно, сделать. Но это уже будет совсем другой маппинг с другими правилами, больше похожий на клонирование.
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: [ANN] Emit Mapper
От: Dog  
Дата: 05.01.10 19:06
Оценка:
IT>>>Как я уже сказал, проблема в том, что при уж очень заумных сценариях object to object проще написать ручками. Но в принципе, я не возражаю. Возможностей меньше. Хотя больше пока никому не было нужно.
Dog>>Re[2]: Маппинг списков
Автор: Dog
Дата: 18.12.09

IT>Что делать в твоём примере, если в A есть обратная ссылка на Foo?
Нету ни циклических ни обратных...

Dog>>Не надо на всё. Напиши в доке, то-то и то-то не поддерживает. Но чтобы User.Bank.Address в User.Bank.Address или вот
Автор: Dog
Дата: 17.12.09
замапило без приседаний.

IT>Можно, конечно, сделать. Но это уже будет совсем другой маппинг с другими правилами, больше похожий на клонирование.
Да. Вот что-то подобное надо.
... а что за другие правила ? Этих что есть хватает вроде, главное обойти и посоздавать всё акуратно.
Re[6]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 05.01.10 20:15
Оценка:
Здравствуйте, IT, Вы писали:

IT>Например, что делать с circle references,

А как пользователь будет вручную писать маппинг, учитывающий circle references? Он тоже будет граф объектов строить? Сомневаюсь. Вот и мэппер пусть делает также. Это ведь не серебряная пуля, а инструмент, позволяющий иногда обходиться без ручного кодирования — не более того.

IT>как обрабатывать наследование,


А какие проблемы с наследованием?

IT>кто должен создавать и должен ли экземпляры вложенных объектов,


ЕМ работает так: по-умолчанию использует дефолтный конструктор. Но если надо, можно задать кастомный:

var mapper = ObjectsMapperManager.DefaultInstance.GetMapper<Source, Destination>(
        new DefaultMapConfig().ConstructBy<Foo>( () => new FooDescendant("hello!") )
    );


IT>должны ли эти экземпляры копироваться по ссылке или создаваться и маппится по-новой.


ЕМ по-умолчанию копирует все по ссылке, но это поведение также можно переопределить либо сразу для всех типов, либо выборочно.

IT>На все эти вопросы есть либо ни одного, либо два-три ответа, которые валидны в дефолтной конфигурации.


Надо лишь дать пользователю возможность ответить на эти вопросы и далее делать все, как он скажет.

T>>Ой

T>>Пофиксено.

IT>Вижу. Производительность сразу просела. Стало даже медленней чем было по именам.


Странно, у меня не практически просела и выше чем была с именами и чем у БЛТ также.

IT>>>Кстати, не думал в реализации GetValuesGetter попробовать убрать инициализацию fieldNum через замену делегата на лету. Будет, конечно, дополнительный косвенный вызов, но если кроме fieldNum ещё и тип поля подсмотреть, то можно будет вызывать не reader.GetValue, а, например, reder.GetInt32 и полностью избавиться от боксинга.


T>>Если на лету менять, то боюсь проблемы с многопоточностью будут.


IT>Какие проблемы? Два потока одновременно проинициализируют одно и тоже поле? Так это ерунда.


А если два потока будут одновременно использовать один мэппер (для одного и того же класса), но работать будут с ридерами разной структуры (разный порядок и тип полей)?
Вообще, как бы там ни было я это поборол путем дифференциации датаридеров. Пользователь может либо сам указать идентификатор ридера (например, в качестве идентификатора можно использовать сам запрос) — это работает чуть быстрей, либо идентификатор может быть построен автоматически на основании имен и типов полей — это чуть медленнее. Также сделал прямой вызов методов типа "GetInt32()" как ты предложил, что на синтетическом тесте дало еще буст в 25% (то есть у БЛТ тоже есть куда расти). Тест:

CREATE TABLE [dbo].[test](
    [col1] [int] NOT NULL,
    [col2] [int] NOT NULL,
    [col3] [int] NOT NULL,
    [col4] [int] NOT NULL,
    [col5] [int] NOT NULL,
    [col6] [int] NOT NULL
)
GO

DECLARE @i INT
SET @i = 0
while (@i < 100)
BEGIN
    INSERT INTO test 
    VALUES
    (
        RAND() * 100, RAND() * 100, RAND() * 100, RAND() * 100, RAND() * 100,  RAND() * 100
    )
    SET @i = @i + 1
END
GO

public class test
{
    public int col1;
    public int col2;
    public int col3;
    public int col4;
    public int col5;
    public int col6;
}


IT>Не нашёл где там про это пишут.

Ну там говориться в том числе об использовании DTO для передачи данных между слоями приложения. Очень часто объекты Linq2Sql или EF стараются не выставлять наружу из уровня доступа к данным, чтобы не тянуть зависимость к ORM на все слои, которые общаются с Data Access Layer'ом. То есть DAL имеет интерфейс на основе DTO — POCO объектов, а внутри он уже мэппит их на соответствующие объекты ORM. Дело в том, что обычно этот мэппинг пишут вручную и это довольно геморройно.
лэт ми спик фром май харт
Re[7]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 06.01.10 14:34
Оценка:
Здравствуйте, Dog, Вы писали:

IT>>Что делать в твоём примере, если в A есть обратная ссылка на Foo?

Dog>Нету ни циклических ни обратных...

А если завтра понадобится?

IT>>Можно, конечно, сделать. Но это уже будет совсем другой маппинг с другими правилами, больше похожий на клонирование.

Dog>Да. Вот что-то подобное надо.
Dog>... а что за другие правила ? Этих что есть хватает вроде, главное обойти и посоздавать всё акуратно.

Вот как раз что-то подобное клонированию сделать универсально не так просто.
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 06.01.10 15:19
Оценка:
Здравствуйте, mrTwister, Вы писали:

IT>>Например, что делать с circle references,

T>А как пользователь будет вручную писать маппинг, учитывающий circle references? Он тоже будет граф объектов строить? Сомневаюсь.

Не надо сомневаться. Я вчера весь вечер убил, чтобы разрулить обратные ссылки. Сегодня буду переписывать всё на двойной проход по дереву, т.к. в один проход задача у меня не решилась. Там, конечно, не совсем просто маппинг, но задача схожая.

T>Вот и мэппер пусть делает также. Это ведь не серебряная пуля, а инструмент, позволяющий иногда обходиться без ручного кодирования — не более того.


Так и обратные ссылки это инструмент. Лучше бы, конечно, без них, но не всегда это получается.

IT>>как обрабатывать наследование,

T>А какие проблемы с наследованием?

В EM ты создаёшь маппер по типам источника и приёмника. Если в качестве источника будет не тип, который был при инициализации маппера, а его наследник, то всё будет пучком или возникнут проблемы?

IT>>кто должен создавать и должен ли экземпляры вложенных объектов,

T>ЕМ работает так: по-умолчанию использует дефолтный конструктор. Но если надо, можно задать кастомный:

А если моя логика подразумевает, что если в целевом объекте ссылка нулевая, то не нужно создавать по ней объекта?

IT>>Какие проблемы? Два потока одновременно проинициализируют одно и тоже поле? Так это ерунда.

T>А если два потока будут одновременно использовать один мэппер (для одного и того же класса), но работать будут с ридерами разной структуры (разный порядок и тип полей)?

Маппер не должен хранить в себе состояние и не будет проблем.

T>Вообще, как бы там ни было я это поборол путем дифференциации датаридеров. Пользователь может либо сам указать идентификатор ридера (например, в качестве идентификатора можно использовать сам запрос) — это работает чуть быстрей, либо идентификатор может быть построен автоматически на основании имен и типов полей — это чуть медленнее. Также сделал прямой вызов методов типа "GetInt32()" как ты предложил, что на синтетическом тесте дало еще буст в 25% (то есть у БЛТ тоже есть куда расти).


Расти всегда есть куда. 25% это очень не плохо. Если раньше я только раздумывал, то теперь точно займусь этим для линка. Спасибо за проверку идеи

IT>>Не нашёл где там про это пишут.

T>Ну там говориться в том числе об использовании DTO для передачи данных между слоями приложения. Очень часто объекты Linq2Sql или EF стараются не выставлять наружу из уровня доступа к данным, чтобы не тянуть зависимость к ORM на все слои, которые общаются с Data Access Layer'ом. То есть DAL имеет интерфейс на основе DTO — POCO объектов, а внутри он уже мэппит их на соответствующие объекты ORM. Дело в том, что обычно этот мэппинг пишут вручную и это довольно геморройно.

Это чисто дизайнерские решения.
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 06.01.10 15:55
Оценка:
Здравствуйте, IT, Вы писали:

IT>Не надо сомневаться. Я вчера весь вечер убил, чтобы разрулить обратные ссылки. Сегодня буду переписывать всё на двойной проход по дереву, т.к. в один проход задача у меня не решилась. Там, конечно, не совсем просто маппинг, но задача схожая.

Ну вот для таких случаев можно вручную написать алгоритм, осуществляющий разруливание обратных ссылок. В принципе, для ЕМ можно написать конфигуратор, который будет это делать при этом не меняя самого ЕМ. Но эта задача встречается достаточно редко, чтобы из-за нее отказываться от реализации фичи полезной в 99% остальных случаев.

IT>В EM ты создаёшь маппер по типам источника и приёмника. Если в качестве источника будет не тип, который был при инициализации маппера, а его наследник, то всё будет пучком или возникнут проблемы?


Только что проверил — все работает нормально. Единственное что поля производного класса конечно никуда копироваться не будут, будут скопированы только поля базового. Если это критично, то можно просто не использовать заранее сгенерированный мэппер.

IT>А если моя логика подразумевает, что если в целевом объекте ссылка нулевая, то не нужно создавать по ней объекта?

Этот вариант использования мне раньше в голову не приходил, но можно добавить конфигурационный метод типа: FilterDestination(value => value != null)
Наверное, я так и сделаю.

IT>Маппер не должен хранить в себе состояние и не будет проблем.


Ага, сейчас так и сделано.

IT>Расти всегда есть куда. 25% это очень не плохо. Если раньше я только раздумывал, то теперь точно займусь этим для линка. Спасибо за проверку идеи


Кстати, что интересно, буст получается не только на value-типах (что ожидаемо), но даже на строках. Интересно, почему?

IT>Это чисто дизайнерские решения.


Верно, но оно очень популярно. Я с ним регулярно сталкиваюсь.
лэт ми спик фром май харт
Re[9]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 07.01.10 20:31
Оценка:
IT>>А если моя логика подразумевает, что если в целевом объекте ссылка нулевая, то не нужно создавать по ней объекта?
T>Этот вариант использования мне раньше в голову не приходил, но можно добавить конфигурационный метод типа: FilterDestination(value => value != null)
T>Наверное, я так и сделаю.

Кстати, добавил
лэт ми спик фром май харт
Re[8]: [ANN] Emit Mapper
От: Dog  
Дата: 11.01.10 08:54
Оценка:
IT>>>Что делать в твоём примере, если в A есть обратная ссылка на Foo?
Dog>>Нету ни циклических ни обратных...
IT>А если завтра понадобится?
Завтра может понадобиться ещё не только это, но это совсем не повод не делать того что необходимо сейчас

IT>>>Можно, конечно, сделать. Но это уже будет совсем другой маппинг с другими правилами, больше похожий на клонирование.

Dog>>Да. Вот что-то подобное надо.
Dog>>... а что за другие правила ? Этих что есть хватает вроде, главное обойти и посоздавать всё акуратно.
IT>Вот как раз что-то подобное клонированию сделать универсально не так просто.
А можно для начала хотя бы сделать не универсально ?
Re[9]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 11.01.10 11:43
Оценка:
Здравствуйте, Dog, Вы писали:

IT>>Вот как раз что-то подобное клонированию сделать универсально не так просто.

Dog>А можно для начала хотя бы сделать не универсально ?

А чем EmitMapper то не устраивает?
лэт ми спик фром май харт
Re[10]: [ANN] Emit Mapper
От: Dog  
Дата: 12.01.10 11:30
Оценка:
Dog>>А можно для начала хотя бы сделать не универсально ?
T>А чем EmitMapper то не устраивает?
Не хочется устраивать из проекта зоопарк
Re[11]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 13.01.10 08:13
Оценка:
Здравствуйте, Dog, Вы писали:

Dog>Не хочется устраивать из проекта зоопарк


С одной стороны да, но с другой задачи О2О сопоставления и ORM — это довольно разные задачи (что наглядно продемонстрировало это обсуждение) и нет ничего страшного в том, чтобы для решения разных задач применялись разные инструменты. Тем более, что у EmitMapper — это один проект (1 длл) без никаких зависимостей, не заставляет использовать никакие атрибуты, наследоваться ни от каких классов, не заставляет следовать никаким правилам и под неё не надо специально подстраиваться.
лэт ми спик фром май харт
Re[10]: [ANN] Emit Mapper
От: vdimas Россия  
Дата: 13.01.10 10:15
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Дак это проблемы BLT. Он другого интерфейса не предоставляет.


Дык BLT реализует интерфейсы или абстрактные классы BO сам, как же ты предварительно создашь неизвестный тип?

T>Плюс к этому BLT при конвертации value типов делает боксинг/анбоксинг. EM обходится без этого.


Да, и в конкретно нашем случае нам пришлось добавить пару сигнатур для ValueType, чтобы эффективно маппить массивы значений. В десяток-другой строк задача, но кроме меня, насколько я смотрю за BLT последние 5 лет, это никому не надо было.
Re[10]: [ANN] Emit Mapper
От: vdimas Россия  
Дата: 13.01.10 10:18
Оценка:
Здравствуйте, mrTwister, Вы писали:

К тому же в тесте ты свой маппер получил однократно, а BLT постоянно достаешь его из синхронизируемого контейнера, хотя мог бы постыпить точно так же. В общем, тест некорректен.
Re[11]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 13.01.10 10:27
Оценка:
Здравствуйте, vdimas, Вы писали:

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


V>К тому же в тесте ты свой маппер получил однократно, а BLT постоянно достаешь его из синхронизируемого контейнера, хотя мог бы постыпить точно так же. В общем, тест некорректен.


Каким образом в BLT можно получить мэппер заранее, чтобы сделать также?
лэт ми спик фром май харт
Re[6]: [ANN] Emit Mapper
От: vdimas Россия  
Дата: 13.01.10 10:33
Оценка:
Здравствуйте, IT, Вы писали:

Ну, молодцы/молодец однозначно. При кол-ве пройденных тестов больше, чем NH, в среднем в 8-10 раз больше производительность на всех видах тестов. Без комментариев.
Re[11]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 13.01.10 11:00
Оценка:
Здравствуйте, vdimas, Вы писали:

T>>Дак это проблемы BLT. Он другого интерфейса не предоставляет.


V>Дык BLT реализует интерфейсы или абстрактные классы BO сам, как же ты предварительно создашь неизвестный тип?


Ну вот реальный вариант использования:
здесь
Автор:
Дата: 30.12.09

private static readonly Mapper<OrgNode, OrgNode> Mapper =
ObjectsMapperManager.DefaultInstance.GetMapper<OrgNode, OrgNode>(new DefaultMapConfig().DeepMap());DefaultMapConfig().DeepMap<OrgNode>());

_savedObject = Mapper.Map<OrgNode, OrgNode>(node);


В случае О2О типы сопоставляемых объектов известны заранее практически всегда. В том 1% случаев, когда это не так, можно использовать интерфейс аналогичный БЛТ и даже тогда ЕМ все равно быстрее. В этой теме было заявлено, что БЛТ — это полноценный О2О мэппер, вот и тестировать его тогда надо согласно вариантам использования О2О мэпперов.

Далее, учитывая, что БЛТ на порядок проще и беднее, чем ЕМ (как О2О мэппер) сравнивать их производительность также не совсем корректно. Например, если бы БЛТ был полноценным мэппером, мне было бы интересно посмотреть на его производительность в сложных случаях типа вложенной nullable структуры, которая доступна через свойство. Или кастомных конверторов/конструкторов. В ЕМ учитывается огромное количество всяких хитрых таких вариантов, причем делается это максимально эффективным способом, как если бы это делал человек кодировал вручную. Ничего этого нет в БЛТ именно по причине того, что он примитивен как О2О мэппер.

T>>Плюс к этому BLT при конвертации value типов делает боксинг/анбоксинг. EM обходится без этого.


V>Да, и в конкретно нашем случае нам пришлось добавить пару сигнатур для ValueType, чтобы эффективно маппить массивы значений.


В EmitMapper по умолчанию доступно 679 типизированных сигнатур для ValueType, плюс пользователь может сам добавлять кастомные конверторы для любых типов которые также будут работать без боксинга/анбоксинга:


public class A
{
    public string fld1;
    public string fld2;
}

public class B
{
    public int fld1 = 1;
    public int fld2 = 2;
}

[TestMethod]
public void Test_CustomConverter2()
{
    A a = Context.objMan.GetMapper<B, A>(
        new DefaultMapConfig().ConvertUsing<int, string>(v => "converted " + v.ToString())
    ).Map(new B());
    Assert.AreEqual("converted 1", a.fld1);
    Assert.AreEqual("converted 2", a.fld2);
}



V>насколько я смотрю за BLT последние 5 лет, это никому не надо было.

А как ты это определил? 99% либо забивают на производительность, либо переписывают код вручную.
лэт ми спик фром май харт
Re[7]: [ANN] Emit Mapper
От: ili Россия  
Дата: 21.01.10 11:00
Оценка:
Здравствуйте, mrTwister, Вы писали:

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


AVK>>А это вовсе не вопрос, потому что проблемы с конкретной удочкой вполне решаемы написанием собственной удочки в крайнем случае.



T>Прекрасно. Сколько надо написать кода для маппинга вложенных структур (в том числе рекурсивных)?


ленно по вечерам — недельку.
рекурсивных эт Parent.Child.Parent object.ReferenceEquals(Parent, Parent.Child.Parent)?
BLT вообще дает возможность мапить чего угодно на чего угодно. То что поставляется штатно, это наиболее часто используемая вещь.
Re[8]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 21.01.10 21:19
Оценка:
Здравствуйте, ili, Вы писали:

ili>ленно по вечерам — недельку.


Это кажется, что легко. Если серьезно подходить к задаче, то окажется, что там много противных нюансов. Например, маппинг в структуры (которые могут быть доступны через свойства), коллекции, отсутствие default-конструкторов, копирование по ссылке или по значению и т.д.

ili>рекурсивных эт Parent.Child.Parent object.ReferenceEquals(Parent, Parent.Child.Parent)?

Да
лэт ми спик фром май харт
Re[9]: [ANN] Emit Mapper
От: ili Россия  
Дата: 22.01.10 06:07
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Это кажется, что легко. Если серьезно подходить к задаче, то окажется, что там много противных нюансов. Например, маппинг в структуры (которые могут быть доступны через свойства), коллекции, отсутствие default-конструкторов, копирование по ссылке или по значению и т.д.


вот про отсутствие дефолтных конструкторов, я, честно признаться не подумал, ну еще день.

имхо, О2О, это скорее вопрос одного конкретного случая, и под конкретные правила BLT очень хорошо решает задачи (задавать правила и в рамках них решать задачу там достаточно просто, и это при учете знания библиотеки немногим выше уровня, описанного в вики). половина тех нюансов что ты отметил этими конкретными правилами просто отметется.
а время на работы, соответственно, еще уменьшится.
вот в этом-то и есть вся сила BLT.
(эт я тут не религию распространяю, эт я опытом делюсь под конкретно заданый вопрос, если что)

ili>>рекурсивных эт Parent.Child.Parent object.ReferenceEquals(Parent, Parent.Child.Parent)?

T>Да

вот это, пожалуй самый гнусный момент если в эмит.маппере он сделан, то скажи куда глянуть, было бы интересно перенять опыт
Re[10]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 22.01.10 07:33
Оценка:
Здравствуйте, ili, Вы писали:

ili>вот про отсутствие дефолтных конструкторов, я, честно признаться не подумал, ну еще день.


ili>имхо, О2О, это скорее вопрос одного конкретного случая, и под конкретные правила BLT очень хорошо решает задачи (задавать правила и в рамках них решать задачу там достаточно просто, и это при учете знания библиотеки немногим выше уровня, описанного в вики). половина тех нюансов что ты отметил этими конкретными правилами просто отметется.

ili>а время на работы, соответственно, еще уменьшится.
ili>вот в этом-то и есть вся сила BLT.
ili>(эт я тут не религию распространяю, эт я опытом делюсь под конкретно заданый вопрос, если что)

Ок, чтобы сделать разговор более предметным, не мог бы ты продемонстрировать этот код. Когда меня спросили про атрибуты для мэппинга я показал несколько строк кода, которые их реализуют. Давай сделаем также?

ili>>>рекурсивных эт Parent.Child.Parent object.ReferenceEquals(Parent, Parent.Child.Parent)?

T>>Да

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


Эта задача решается через построение графа объектов и это можно сделать через кастомную конфигурацию к EM. По-умолчанию ЕМ граф не строит, но если хочешь, я могу вечером накидать несколько строк кода, которые показывают, как это сделать с помощью ЕМ.

Вообще, я немного потерял контекст обсуждения, выше я имел ввиду рекурсивные структуры данных типа списка. То есть когда структура данных циклическая, а граф нециклический.
лэт ми спик фром май харт
Re[10]: [ANN] Emit Mapper
От: cadet354 Россия
Дата: 22.01.10 07:42
Оценка:
Здравствуйте, ili, Вы писали:



ili>вот про отсутствие дефолтных конструкторов, я, честно признаться не подумал, ну еще день.

тебе понадобилось 20 минут для того чтоб маппинг на record F# заработал

хотя при o2o сложностей наверняка больше: вложенность, циклические связки и т.д.
Из практических вещей для меня Emit мог бы пригодится например возможностью мапить model на view в MVC.
например есть два-три объекта которые являются моделью в контроллере, нужно взять пару свойств из одного и другого,
и замапить на объект который будет использоваться для view.
... << RSDN@Home 1.2.0 alpha 4 rev. 1270>>
Re[11]: [ANN] Emit Mapper
От: ili Россия  
Дата: 22.01.10 08:00
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Ок, чтобы сделать разговор более предметным, не мог бы ты продемонстрировать этот код. Когда меня спросили про атрибуты для мэппинга я показал несколько строк кода, которые их реализуют. Давай сделаем также?


давай только это не пара строк кода скажем, я могу сказать куда смотреть (наследование от ObjectMapper, возможно с добавлением MetaDataProvider)
если интересен именно код, то нарисуй тест, который BLT валит, а я приведу его в рабочее состояние (сразу скажу приводить буду "ленно", просто естт джоб, который сейчас надо делать, а вечером спать охота очень )
только пожелей меня чутка, обойдемся без циклических ссылок по object.ReferenceEquals(Parent, Parent.Child.Parent) и ограничимся наличием дефолтных конструкторов.

ili>>>>рекурсивных эт Parent.Child.Parent object.ReferenceEquals(Parent, Parent.Child.Parent)?

T>>>Да

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


T>Эта задача решается через построение графа объектов и это можно сделать через кастомную конфигурацию к EM. По-умолчанию ЕМ граф не строит, но если хочешь, я могу вечером накидать несколько строк кода, которые показывают, как это сделать с помощью ЕМ.


было бы интересно, если не затруднит.

T>Вообще, я немного потерял контекст обсуждения, выше я имел ввиду рекурсивные структуры данных типа списка. То есть когда структура данных циклическая, а граф нециклический.


эээ... при этих словах я почувствовал себя полным ничтожеством рядом с гигантом мысли переведи, пожалуйста =)
Re[11]: [ANN] Emit Mapper
От: ili Россия  
Дата: 22.01.10 08:05
Оценка:
Здравствуйте, cadet354, Вы писали:

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


ili>>вот про отсутствие дефолтных конструкторов, я, честно признаться не подумал, ну еще день.

C>тебе понадобилось 20 минут для того чтоб маппинг на record F# заработал

эмн... там какраз был в наличии вполне конкретный случай. как я и говорил, конкретику BLT решает хорошо и быстро.
бишь то, что я нарисовал для record годится только для него и только при условии что имена параметров конструктора совпадают с именами полей.
Re[12]: [ANN] Emit Mapper
От: cadet354 Россия
Дата: 22.01.10 09:18
Оценка:
Здравствуйте, ili, Вы писали:


ili>эмн... там какраз был в наличии вполне конкретный случай. как я и говорил, конкретику BLT решает хорошо и быстро.

ili>бишь то, что я нарисовал для record годится только для него и только при условии что имена параметров конструктора совпадают с именами полей.
Думаю прикрутить чтение имена параметров из атрибутов не займет много времени.
... << RSDN@Home 1.2.0 alpha 4 rev. 1270>>
Re: [ANN] Emit Mapper
От: i1yich  
Дата: 25.04.10 05:38
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>http://emitmapper.codeplex.com


T>Emit Mapper — это мощная легковесная библиотека для проецирования одних объектов на другие. Имеет следующие особенности:


Можно ли портировать под .NET 2.0?

Я посмотрел, из 3.5 там используется только System.Core. Для net2.0 ее вполне можно заменить на LinqBridge. Там есть реализации Enumerable, Func<> и Action<> и определен ExtensionAttribute, единственное из необходимого твоему мапперу, чего там нет — это класса HashSet, но его можно заменить на HashTable.
Re[2]: [ANN] Emit Mapper
От: Legion13  
Дата: 25.04.10 16:22
Оценка:
Здравствуйте, i1yich, Вы писали:

I>Я посмотрел, из 3.5 там используется только System.Core. Для net2.0 ее вполне можно заменить на LinqBridge. Там есть реализации Enumerable, Func<> и Action<> и определен ExtensionAttribute, единственное из необходимого твоему мапперу, чего там нет — это класса HashSet, но его можно заменить на HashTable.


Можете просто взять System.Core из поставки FW 3.5
Re[11]: [ANN] Emit Mapper
От: Mr.Cat  
Дата: 25.04.10 16:27
Оценка:
Здравствуйте, mrTwister, Вы писали:
T>Эта задача решается через построение графа объектов и это можно сделать через кастомную конфигурацию к EM. По-умолчанию ЕМ граф не строит, но если хочешь, я могу вечером накидать несколько строк кода, которые показывают, как это сделать с помощью ЕМ.

Мне бы, кстати, тоже было интересно. Хотел на днях прикрутить EM для маппинга графов, но не смог.
Re: [ANN] Emit Mapper
От: cadet354 Россия
Дата: 06.05.10 14:37
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>http://emitmapper.codeplex.com


насколько эта библиотека потокобезопасна?
например такой подход
private static readonly ObjectsMapper<ActivationCodeRequest, SoldLicense> requestToLicense =
            ObjectMapperManager.DefaultInstance.GetMapper<ActivationCodeRequest, SoldLicense>();
            // и потом где-то в методах
            public SoldLicense GetLicense(ActivationCodeRequest request)
            {
              // код поскипан
              SoldLicense license=requestToLicense.Map(request);
              // код поскипан
              return license;
            }

жизнеспособен?
... << RSDN@Home 1.2.0 alpha 4 rev. 1270>>
Re[12]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 07.05.10 07:33
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

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

T>>Эта задача решается через построение графа объектов и это можно сделать через кастомную конфигурацию к EM. По-умолчанию ЕМ граф не строит, но если хочешь, я могу вечером накидать несколько строк кода, которые показывают, как это сделать с помощью ЕМ.

MC>Мне бы, кстати, тоже было интересно. Хотел на днях прикрутить EM для маппинга графов, но не смог.



К сожалению, я ошибся, в текущей версии это не сделать Не хватает метода расширения, чтобы можно было получить объект после того, как он был создан, но до того, как началось копирование его свойств.
лэт ми спик фром май харт
Re[14]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 07.05.10 11:38
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

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

T>>К сожалению, я ошибся, в текущей версии это не сделать Не хватает метода расширения, чтобы можно было получить объект после того, как он был создан, но до того, как началось копирование его свойств.
MC>Или возможности вызвать копирования свойств из кастомного ConvertUsing.

Этот вариант даже лучше!
лэт ми спик фром май харт
Re[15]: [ANN] Emit Mapper
От: Collega  
Дата: 17.05.10 09:16
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Здравствуйте, Mr.Cat, Вы писали:


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

T>>>К сожалению, я ошибся, в текущей версии это не сделать Не хватает метода расширения, чтобы можно было получить объект после того, как он был создан, но до того, как началось копирование его свойств.
MC>>Или возможности вызвать копирования свойств из кастомного ConvertUsing.

T>Этот вариант даже лучше!


Добрый!

Есть такая ситуация:


public class ParentClass
{
    public ParentClass()
    {    
        Child = new ChildClass();
    }

    public ChildClass Child
    {
        get;
        private set;
    }
}


Нужно сделать копию ParentClass. Однако вложенный ChildClass не мапится, т.к. сеттер свойства ParentClass.Child приватный. Существуют ли варианты заставить его мапиться не меняя private set на public set?
Re: [ANN] Emit Mapper
От: Аноним  
Дата: 03.07.10 10:28
Оценка:
Здравствуйте, mrTwister, Вы писали:

А он умеет маппить xml структуры?
Re: [ANN] Emit Mapper
От: cadet354 Россия
Дата: 06.09.10 08:12
Оценка:
Здравствуйте, mrTwister

а как получить аналог ForMember из automapper?
... << RSDN@Home 1.2.0 alpha 4 rev. 1270>>
Re: [ANN] Emit Mapper
От: Аноним  
Дата: 09.09.10 12:46
Оценка:
А можно практический вопрос? хочется посмотреть на товар лицом )

Есть класс Person со свойствами Фамилия Имя Отчество и т.д.
и есть xml
<xml><Person Фамилия="..." Имя="..." Отчество="..."></xml>

как с помощью Emit Mapper замапить поля на созданный экземпляр класса Person?
Re[2]: [ANN] Emit Mapper
От: IT Россия linq2db.com
Дата: 09.09.10 13:37
Оценка:
Здравствуйте, Аноним, Вы писали:

А>как с помощью Emit Mapper замапить поля на созданный экземпляр класса Person?


Никак. Это мапер объектов в объекты.
Если нам не помогут, то мы тоже никого не пощадим.
Re: [ANN] Emit Mapper
От: LF  
Дата: 23.09.10 13:33
Оценка:
Добрый день,
подскажите, как получить Flattening из automapper?
Спасибо.
Re[2]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 24.09.10 11:04
Оценка:
Здравствуйте, LF, Вы писали:

LF>Добрый день,

LF>подскажите, как получить Flattening из automapper?
LF>Спасибо.

Там в примерах есть:
http://emitmapper.codeplex.com/SourceControl/changeset/view/55578#1192663

Использование:
http://emitmapper.codeplex.com/SourceControl/changeset/view/55578#691132
лэт ми спик фром май харт
Re[3]: [ANN] Emit Mapper
От: LF  
Дата: 24.09.10 11:22
Оценка:
T>Там в примерах есть:
T>http://emitmapper.codeplex.com/SourceControl/changeset/view/55578#1192663

T>Использование:

T>http://emitmapper.codeplex.com/SourceControl/changeset/view/55578#691132

Спасибо, не плохо бы такое на главную страницу вывести, честно говоря не пришло в голову,
что в транке может быть больше примеров чем описано в документации.
Re: [ANN] Emit Mapper
От: FreddieM  
Дата: 07.11.10 17:20
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>http://emitmapper.codeplex.com


T>Emit Mapper — это мощная легковесная библиотека для проецирования одних объектов на другие. Имеет следующие особенности:


T>1) Очень быстрая. Работает через Emit с производительностью рукописного кода. По разным тестам в 150-600 раз быстрее чем AutoMapper. Бенчмарк


T>2) Очень гибкая. Проецировать можно что угодно на что угодно. Например, датаридер на объекты, объекты на SQL команды (UPDATE, INSERT), объекты на строку (сериализация), строку на объекты (десериализация) и так далее. Короче говоря, в рантайме можно задать произвольный меппинг чего угодно на что угодно, который работает со скоростью рукописного кода.


Проект ещё поддерживается? Он ещё интересен автору? Хочу попробовать использовать в реальном коммерческом продукте, а на CodePlex'е beta, которая не обновлялась с января...

PS: С .NET Framework 4.0 проблем не будет?
Re[2]: [ANN] Emit Mapper
От: mrTwister Россия  
Дата: 11.11.10 08:25
Оценка:
Здравствуйте, FreddieM, Вы писали:

FM>Проект ещё поддерживается? Он ещё интересен автору? Хочу попробовать использовать в реальном коммерческом продукте, а на CodePlex'е beta, которая не обновлялась с января...

Проект поддерживается, баги, если таковые обнаружатся, пофиксятся.

FM>PS: С .NET Framework 4.0 проблем не будет?

Не должно.
лэт ми спик фром май харт
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.