AutoMapper vs ValueInjecter [закрыто]

209

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

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

Rookian
источник
2
Еще один, который я часто упоминал, - это EmitMapper .
Adrianbanks
1
Как насчет клея? glue.codeplex.com Выглядит как отличный проект, но я еще не пробовал. Я буду в течение следующего месяца, хотя. Я также видел проект под названием EmitMapper emitmapper.codeplex.com
Trygve
Смотрите статью, рассказывающую об этих двух инструментах - devproconnections.com/development/…
Джордж Бирбилис

Ответы:

170

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

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

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

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

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

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

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

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

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

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

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

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

различия:

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

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

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

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

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

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

Ома
источник
5
Для бога любви, пожалуйста, скажите мне, что ValueInjector может взять глубокий график ViewModel и отобразить в / из глубокого графа Business Entity и отобразить все, что точно так же, без работы, и что мне нужно только указать, как обращаться с тем, что отличается. Я надеялся, что AutoMapper добавит эту возможность, но она так и не была реализована, и у меня не было времени написать свой собственный Auto Mapper.
Крис Марисик
3
@Chris Marisic, вы можете использовать его, чтобы сделать это, на случай, если вы имеете в виду глубокое клонирование, я сделал одну инъекцию однажды, которая делает это рекурсивно, но не работает со свойствами коллекций. Valueinjecter.codeplex.com/Thread/View.aspx?ThreadId=236126 , или вы можете сделать Flat ViewModel и использовать выравнивание и разглаживание, это было бы легко
Omu
Объекты ViewModel и Domain должны быть похожими, но разными, поэтому это не чистый клон. 90% свойств обычно являются точным типом и именем, ViewModels часто заканчивают списками выбора и связанными с ними вещами, которые я бы хотел игнорировать, возвращаясь в домен. Оба, скорее всего, будут иметь коллекции объектов на них.
Крис Марисик
27
<pedant>Выглядит круто, но, возможно, это должен быть ValueInjectOr? </pedant>
Крейг Штунц
1
но почему-то это эр :)
Omu
59

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

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

Если вы хотите сделать это, AutoMapper работает очень хорошо для вас. AutoMapper не очень хорошо работает:

  • Заполнение существующих объектов
  • Unflattening

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

Джимми Богард
источник
1
@Jimmy Bogard Видите ли вы, что заполнение существующих объектов когда-либо попадет в список функций для AutoMapper?
Роман
Я не пробовал ValueInjecter, но для того, что нам было нужно, Autopper очень мощный.
richb01
Я думаю, что самая важная вещь здесь - проверяемость. При переименовании и рефакторинге вещей это очень помогает.
Кугель
55

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

myObject.InjectFrom(otherObject);

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

Адриан Григоре
источник
1
this objectметод расширения есть?
Крис Марисик
2
Как я могу отделить свой код от ValueInjecter? Мне кажется, что у меня всегда есть зависимость от ValueInjecter, т.е. в моем веб-проекте, потому что я использую ValueInjecter (метод расширения) для данного объекта ПРЯМО.
Rookian
1
@ Rookian, честно говоря, это не та проблема, о которой стоит задуматься. Вы можете зависеть от интерфейса, подобного упомянутому @Omu, поэтому, если вы когда-нибудь смените мапперы, вы можете сэкономить некоторую работу (вероятно, не очень). Этот тип зависимости слишком сложно абстрагировать, если только вы не хотите получить полноценный AOP, который, к сожалению, просто невозможно отменить, поскольку .NET не помогает правильно обеспечить поддержку AOP. Теперь вы можете отменить некоторые сопоставления, особенно если вы используете MVC и пишете фильтры действий, которые обрабатывают сопоставление ViewModel / DomainModel.
Крис Марисик
13
почему обертка - лучшее решение? Единственное, что вам нужно сделать, если вы хотите переключить маппер, это реализовать InjectFrom()метод расширения самостоятельно.
jgauffin
1
Я пробовал и то и другое, и я предпочитаю AutoMapper. Я использовал его для небольшой части моей системы, где я сопоставляю сущности с классами, сгенерированными Linq2Sql. Простое отображение как StockTotalQuantity -> stock_size_quantity или UserId -> user_id по умолчанию работало с AutoMapper. Это не сработало с ValeInjecter даже после добавления конвекции. Придерживаясь AutoMapper сейчас.
Артур Кендзиор
27

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

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

Модель, созданная структурой объекта (сначала модель):

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?)

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

Danh
источник
1
Возможно, вам следует задать этот вопрос в отдельном вопросе, помеченном asp.net-mvc и передовыми методами, ViewModel ..., я не вижу проблем, если он хорошо работает для вас, но я уверен, что у кого-то могут быть разные мнения
Ому
Хорошо узнав больше MVC. Теперь я могу ответить на мой вопрос. Чтобы обновить исходную модель при возврате заполненной модели представления, можно использовать функцию UpdateModel (), предоставляемую mvc.
ДанХ
1
UpdateModel () используется для заполнения модели, которая представляет представление, и аналогична выполнению действия (модель MyModelClasss)
Omu
Верно, но если вы хотите иметь отдельную модель представления, например, для модели репозитория, то ее можно использовать, чтобы указать, что сопоставление тривиально (а часто и так). Конечно, если более сложный ValueInjector вступает в свои права.
ДанХ
1
Я думаю, что можно привести аргумент, что вы не должны просто возвращать свои свойства в модель вашего домена - вы должны использовать методы, которые придают смысл этому.
Майк Коул