AutoMapper против ValueInjecter

Каждый раз, когда я ищу материал AutoMapper в StackOverflow, я читаю что-то о ValueInjecter.

Может ли кто-нибудь сказать мне плюсы и минусы между ними (производительность, функции, использование API, расширяемость, тестирование)?


person Rookian    schedule 11.01.2011    source источник
comment
Еще один, который я часто упоминал, - это EmitMapper.   -  person adrianbanks    schedule 12.01.2011
comment
А что насчет клея? glue.codeplex.com Похоже, тоже отличный проект, но я еще не пробовал его. Я сделаю это в течение следующего месяца. Я также видел проект под названием EmitMapper emitmapper.codeplex.com   -  person Trygve    schedule 28.04.2011
comment
См. Статью об этих двух инструментах - devproconnections.com/development/   -  person George Birbilis    schedule 05.09.2014


Ответы (4)


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

Я действительно не люблю много писать или писать много monkey code вроде:

Prop1.Ignore, Prop2.Ignore etc.
CreateMap<Foo,Bar>(); CreateMap<Tomato, Potato>(); etc.

ValueInjecter - это что-то вроде Mozilla с ее плагинами, вы создаете ValueInjection и используете их.

есть встроенные инъекции для сглаживания, сглаживания, а некоторые предназначены для наследования

и он работает больше в аспекте типа, вам не нужно указывать все свойства один к одному, вместо этого вы делаете что-то вроде:

взять все свойства int из источника, имя которого заканчивается на «Id», преобразовать значение и установить каждое свойство в исходном объекте с тем же именем без суффикса Id, и его тип наследуется от Entity, и тому подобное < / em>

одно очевидное отличие: ValueInjecter используется даже в формах окна со сглаживанием и сглаживанием, вот насколько он гибкий

(отображение от объекта к элементам управления формы и обратно)

Automapper, не может использоваться в формах Windows, без unflatenning, но у него есть хорошие вещи, такие как сопоставление коллекций, поэтому, если вам это нужно с ValueInjecter, вы просто делаете что-то вроде:

foos.Select(o => new Bar().InjectFrom(o));

вы также можете использовать ValueInjecter для сопоставления из анонимных и динамических объектов

различия:

  • automapper создает конфигурацию для каждой возможности сопоставления CreateMap ()

  • valueinjecter вводить из любого объекта в любой объект (также бывают случаи, когда вы вводите из объекта в тип значения)

  • автомаппер имеет встроенное уплощение, и только для простых типов или из одного и того же типа, и в нем нет выравнивания

  • valueinjecter, только если он вам нужен, вы делаете target.InjectFrom<FlatLoopValueInjection>(source); also <UnflatLoopValueInjection>, а если хотите от Foo.Bar.Name of type String до FooBarName of type Class1, вы наследуете FlatLoopValueInjection и указываете это

  • automapper отображает свойства с одинаковыми именами по умолчанию, а для остальных вы должны указывать одно за другим и делать такие вещи, как Prop1.Ignore (), Prop2.Ignore () и т. д.

  • valueinjecter имеет инъекцию по умолчанию .InjectFrom (), которая выполняет свойства с тем же именем и типом; для всего остального вы создаете свои собственные инъекции значений с индивидуальной логикой / правилами сопоставления, больше похожими на аспекты, например от всех свойств типа Foo до всех свойств типа Bar

person Omu    schedule 12.01.2011
comment
Для бога любви, пожалуйста, скажите мне, что ValueInjector может взять ViewModel с глубоким графом и сопоставить с бизнес-объектом с глубоким графом и сопоставить все, что абсолютно одинаково, без каких-либо усилий, и что мне нужно только указать, как обрабатывать то, что отличается. Я надеялся, что AutoMapper добавит эту возможность, но она так и не реализовалась, и у меня не было времени написать свой собственный автоматический картограф. - person Chris Marisic; 12.01.2011
comment
@Chris Marisic, вы можете использовать это, если вы имеете в виду глубокое клонирование, я сделал одну инъекцию, когда это вроде как делает это рекурсивно, но не работает для свойств коллекций valueinjecter.codeplex.com/Thread/View.aspx?ThreadId=236126, или вы можете создать Flat ViewModel и использовать выравнивание и выравнивание это было бы легко - person Omu; 12.01.2011
comment
Сущности ViewModel и Domain будут похожими, но разными, поэтому это не будет чистый клон. 90% свойств обычно имеют точный тип и имя, ViewModels часто заканчиваются списками SelectLists и прочими связанными с ними вещами, которые я хотел бы игнорировать, возвращаясь в домен. Хотя на обоих, скорее всего, есть коллекции объектов. - person Chris Marisic; 13.01.2011
comment
@Chris Marisic, в демонстрациях asp.net mvc demo и модульных тестах показано много такого рода вещей, загрузите их, поиграйте с ними немного, и вы увидите, насколько это просто - person Omu; 13.01.2011
comment
Мне нравится аспектный способ;) Но разве это возможно только с ValueInjecter: o? - person Rookian; 13.01.2011
comment
@Rookian ну да, если автомаппер не может сделать что-то подобное, но я этого не знаю, может быть, Джимми ответит на этот вопрос - person Omu; 13.01.2011
comment
@ Ому, да, было бы очень интересно, если бы он так - person Rookian; 14.01.2011
comment
@Omu, что вы можете сказать о тестировании или как узнать, что целевой объект будет правильно заполнен? - person Rookian; 27.01.2011
comment
@Rookian в большинстве случаев это просто очевидно (всегда для меня), но вы можете написать модуль, тест и убедиться в этом, у automapper есть метод, который вы можете поместить в модульный тест и убедиться, что ваши конфигурации сопоставления верны, например что вы не забыли указать необходимую конфигурацию и т. д. (vi не требует конфигурации, поэтому нет метода :)) - person Omu; 27.01.2011
comment
<pedant> Выглядит круто, но, может быть, это должен быть ValueInjectOr? </pedant> - person Craig Stuntz; 01.03.2011
comment
но почему-то это э-э :) - person Omu; 29.03.2011
comment
Не правда ли: foos.Select (o = ›(Bar) new Bar (). InjectFrom (o)); Поскольку подписью является объект InjectFrom (этот объект-цель, объект-источник); Возможное улучшение, устраняющее необходимость в приведении типов, - это TTarget InjectFrom ‹TTarget› (эта цель TTarget, источник объекта), где TTarget: class; - person Danny Varod; 07.04.2011
comment
@Danny, в зависимости от контекста, может быть много разных вещей - person Omu; 07.04.2011
comment
как вы сопоставляете один список с другим с помощью valueinjecter? - person user20358; 30.11.2012
comment
@ user20358 вы используете foreach и выполняете InjectFrom для каждого объекта в списке - person Omu; 30.11.2012
comment
Спасибо, Чак. Вот чем я сейчас занимаюсь. Планируется ли что-то подобное в будущем? где мне не придется перебирать каждый элемент в списке. В настоящий момент я пишу уровень данных и хочу иметь возможность сразу же назначать результаты моего 'var records = {some linQ query} .ToList ()' соответствующему пользовательскому объекту dtoListObject. что-то вроде dtoListObject.InjectFrom (records); Есть предложения, кроме того, что вы сказали выше? - person user20358; 01.12.2012
comment
@ user20358 вы всегда можете иметь свой собственный класс или некоторые методы в классе Utils, которые выполняют некоторые настраиваемые сопоставления или добавляют функции, которые вам нужны. - person Omu; 03.12.2012
comment
Есть ли в VulueInjecter что-нибудь параллельное поддержке проекции Queryable в Automapper? - person Iravanchi; 11.08.2014
comment
В настоящее время я смотрю, какой из них использовать, одна вещь, которую я сразу вижу, которая может быть актуальной, - это AutoMapper, похоже, он обновляется на регулярной основе, тогда как ValueInjecter не обновлялся в течение почти 3 лет на NuGet. - person JsonStatham; 05.02.2015

Поскольку я никогда не использовал другие инструменты, я могу говорить только об AutoMapper. При создании AutoMapper у меня было несколько целей:

  • Поддержка сведения к немым объектам DTO
  • Поддержка очевидных сценариев из коробки (коллекции, перечисления и т. Д.)
  • Уметь легко проверять сопоставления в тесте
  • Разрешите граничные случаи для разрешения значений из других мест (настраиваемое сопоставление типов -> типов, сопоставление отдельных элементов и некоторые действительно сумасшедшие граничные случаи).

Если вы хотите делать это, AutoMapper отлично подойдет вам. AutoMapper не справляется с такими задачами:

  • Заполнение существующих объектов
  • Неприятный

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

person Jimmy Bogard    schedule 30.03.2011
comment
@ Джимми Богард: Вы видите, что функция заливки существующих объектов когда-либо попадет в список функций AutoMapper? - person Roman; 08.08.2011
comment
Я не пробовал ValueInjecter, но для того, что нам нужно, automapper очень мощный. - person richb01; 03.05.2012
comment
Я думаю, что самое главное здесь - это проверяемость. При переименовании и рефакторинге это огромная помощь. - person Kugel; 13.02.2014

Я пробовал оба и предпочитаю ValueInjecter, потому что это очень просто:

myObject.InjectFrom(otherObject);

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

person Adrian Grigore    schedule 12.01.2011
comment
this object есть метод расширения? - person Chris Marisic; 13.01.2011
comment
Как я могу отделить свой код от ValueInjecter? Мне кажется, что всегда есть зависимость от ValueInjecter, то есть в моем веб-проекте, потому что я использую ValueInjecter (метод расширения) для данного объекта НЕПОСРЕДСТВЕННО. - person Rookian; 13.01.2011
comment
@Rookian, вы также можете использовать интерфейс IValueInjecter вместо статического расширения и выполнить injecter.Inject (myObject, otherObject) valueinjecter .codeplex.com / документация - person Omu; 13.01.2011
comment
@Rookian, честно говоря, это не та проблема, над которой стоит слишком много думать. Вы можете полагаться на интерфейс, подобный упомянутому @Omu, поэтому, если вы когда-нибудь измените мапперы, вы можете сэкономить часть работы (вероятно, не очень). От этого типа зависимости слишком сложно абстрагироваться, если только вы не хотите перейти в полноценный АОП, который, к сожалению, во многих случаях просто отменяется, поскольку .NET не помогает правильно обеспечить поддержку АОП. Теперь вы можете AOP убрать часть сопоставления, особенно если вы используете MVC и пишете фильтры действий, которые обрабатывают сопоставление ViewModel / DomainModel. - person Chris Marisic; 13.01.2011
comment
@Rookian, вы также можете создать свой собственный класс сопоставления в качестве оболочки для инъекций. - person Omu; 14.01.2011
comment
да, на мой взгляд, обертка была бы лучшим вариантом - person Rookian; 21.01.2011
comment
почему обертка - лучшее решение? Единственное, что вам нужно сделать, если вы хотите переключить mapper, - это самостоятельно реализовать метод расширения InjectFrom(). - person jgauffin; 23.03.2011
comment
@jgauffin да, это тоже хороший вариант :) - person Rookian; 28.03.2011
comment
Я пробовал и то, и другое, и мне больше нравится AutoMapper. Я использовал его для небольшой части моей системы, где я сопоставляю сущности с классами, созданными Linq2Sql. Простое сопоставление как StockTotalQuantity - ›stock_size_quantity или UserId -› user_id действительно работает с AutoMapper по умолчанию. Это не работало с ValeInjecter даже после добавления конвекции. Пока придерживаюсь AutoMapper. - person Artur Kędzior; 11.01.2012

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

Однако, что наиболее важно, это позволяет обратное отображение. Теперь мне может чего-то не хватать, поскольку Джимми упоминает, что он не видит варианта использования там, где это необходимо, поэтому, возможно, у меня неправильный шаблон, но мой вариант использования заключается в том, что я создаю объект ViewModel из моего ORM. Затем я показываю это на своей веб-странице. После того, как пользователь закончит, я верну ViewModel в виде httppost, как это преобразовать обратно в исходные классы ORM? Я хотел бы узнать шаблон с автомаппером. С ValueInjector это тривиально, и даже неплохо. например, создание нового объекта

Модель, созданная entityframework (сначала модель):

public partial class Family
{ 
    public int Id { get; set; }
    public string FamilyName { get; set; }

    public virtual Address Address { get; set; }
}

public partial class Address
{
    public int Id { get; set; }
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string TownCity { get; set; }
    public string County { get; set; }
    public string Postcode { get; set; }

    public virtual Family Family { get; set; }
}

ViewModel (которую я могу украсить валидаторами):

public class FamilyViewModel
{
    public int Id { get; set; }
    public string FamilyName { get; set; }

    public int AddressId { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string AddressTownCity { get; set; }
    public string AddressCounty { get; set; }
    public string AddressPostcode { get; set; }
}

ViewController:

    //
    // GET: /Family/Create

    public ActionResult Create()
    {
        return View();
    } 

    //
    // POST: /Family/Create

    [HttpPost]
    public ActionResult Create(FamilyViewModel familyViewModel)
    {
        try
        {
            Family family = new Family();
            family.InjectFrom<UnflatLoopValueInjection>(familyViewModel);
            db.Families.Add(family);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

На мой взгляд, нет ничего проще?

(Итак, возникает вопрос, что не так с шаблоном, с которым я столкнулся (и, похоже, многие другие так поступают), что он не рассматривается как ценность для AutoMapper?)

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

person DanH    schedule 15.04.2011
comment
вероятно, вам также следует задать этот вопрос в отдельном вопросе, помеченном asp.net-mvc и передовыми практиками, ViewModel ..., atm. Я не вижу никаких проблем, если это хорошо для вас, но я уверен, что у кого-то могут быть разные мнения - person Omu; 15.04.2011
comment
Хорошо узнав больше mvc. Теперь я могу ответить на свой вопрос. Способ обновления исходной модели, когда вы получаете обратно заполненную модель представления, заключается в использовании функции UpdateModel (), которую предоставляет mvc. - person DanH; 06.06.2011
comment
UpdateModel () используется для заполнения модели, представляющей представление, и аналогичен выполнению действия (модель MyModelClasss). - person Omu; 06.06.2011
comment
Верно, но если вы хотите иметь отдельную модель представления, например, модель репозитория, то ее можно использовать для заполнения этого представления, предполагая, что отображение тривиально (а это часто бывает). Конечно, если придет более сложный ValueInjector. - person DanH; 25.06.2011
comment
Я думаю, что решение, которое я собираюсь предложить, может не принадлежать этой теме. Однако вот что я бы сделал. Я бы поручил эту работу бизнес-службам. Таким образом, MVC ничего не знает о модели данных, он знает только о модели предметной области. Бизнес-сервисы взаимодействуют как с моделью данных, так и с моделью предметной области и выполняют однонаправленные преобразования с помощью Automapper, ValueInjector или вашего собственного настраиваемого сопоставителя. - person daehaai; 11.07.2011
comment
Я думаю, можно было бы привести аргумент, что вы не должны просто возвращать свои свойства в свою модель предметной области - вы должны использовать методы, которые добавляют к этому значение. - person Mike Cole; 23.12.2011
comment
Должен сказать, что я отошел от этой схемы внедрения, когда создавал уровни своего веб-приложения. Поэтому в основном используются методы для изменения данных в бэкэнде, а не для передачи объектов. Это может быть результатом того, что ORM не используется ... - person DanH; 03.01.2012
comment
@DanH - Я думаю, что ваш второй параграф и начальное настроение верны независимо от метода UpdateModel, если ваш базовый объект имеет более одного базового класса модели, составляющего вашу ViewModel, правильно? - person atconway; 02.08.2012
comment
Конечно, он действителен, если подходит для вашего случая использования. В основном я нахожу проекцию для удаления полей, которые я не хочу отправлять клиенту или компоновки данных, и если я перехожу в стиль Json, то в эти дни я обнаружил, что использую linq для выбора в анонимный класс, если он не будет повторно использован в нескольких места. Когда данные возвращаются на сервер, это обычно более простая модель, например Возвращается форма, а не сложная модель страницы. Таким образом, подход к модели обновления / входящей привязки обычно подходит для этой задачи. - person DanH; 03.08.2012