AutoMapper vs ValueInjecter [닫기]


209

StackOverflow에서 AutoMapper를 찾을 때마다 ValueInjecter 에 대해 읽습니다 .

누군가 그들 사이의 장단점 (성능, 기능, API 사용, 확장 성, 테스트)을 말해 줄 수 있습니까?


2
내가 많이 언급 한 또 다른 것은 EmitMapper 입니다.
adrianbanks

1
접착제는 어떻습니까? glue.codeplex.com 훌륭한 프로젝트처럼 보이지만 아직 시도하지 않았습니다. 그래도 다음 달에하겠습니다. 또한 EmitMapper emitmapper.codeplex.com
Trygve

- 그 두 가지 도구에 대해 말하기 기사보기 devproconnections.com/development/...
조지 Birbilis

답변:


170

ValueInjecter 의 제작자로서 간단하고 유연한 것을 원했기 때문에 내가 그렇게했다고 말할 수 있습니다.

나는 정말로 많이 쓰는 것을 좋아하지 않으며 다음과 같이 많이 쓰는 것을 좋아하지 않습니다 monkey code.

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

ValueInjecter는 플러그인을 갖춘 mozilla와 같은 것입니다. ValueInjections 를 만들어서 사용하십시오.

납작하게, 납작하게하기위한 내장 주사가 있으며, 일부는 상속되도록되어 있습니다.

그리고 측면 유형의 방식으로 더 많이 작동하므로 모든 속성을 일대일로 지정할 필요가 없으며 대신 다음과 같은 작업을 수행하십시오.

이름이 "Id"로 끝나는 모든 int 속성을 소스에서 가져 와서 값을 변환하고 ID 접미사없이 동일한 이름을 가진 소스 객체의 속성으로 각각 설정하고 유형은 Entity에서 상속됩니다.

명백한 차이점 중 하나는 ValueInjecter가 평탄화 및 전개 해제 기능이있는 Windows 양식에서도 사용됩니다.

(객체에서 폼 컨트롤로 다시 매핑)

Automapper, Windows 형태로는 사용할 수없고 전개도 해제되지 않지만 컬렉션 매핑과 같은 좋은 기능이 있으므로 ValueInjecter로 필요한 경우 다음과 같은 작업을 수행합니다.

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

ValueInjecter를 사용하여 익명동적 객체 에서 매핑 할 수도 있습니다.

차이점 :

  • automapper는 각 맵핑 가능성에 대한 구성을 작성합니다. CreateMap ()

  • valueinjecter는 모든 객체에서 객체로 주입합니다 (객체에서 valuetype으로 주입하는 경우도 있습니다)

  • automapper에는 flattening이 내장되어 있으며 단순한 유형 또는 동일한 유형의 경우에만 평탄화되지 않습니다.

  • valueinjecter 당신은 당신이 그것을 필요로하는 경우에만 target.InjectFrom<FlatLoopValueInjection>(source); also <UnflatLoopValueInjection> 당신이에서 원하는 경우 Foo.Bar.Name of type StringFooBarName of type Class1당신이 FlatLoopValueInjection을 상속하고이를 지정

  • automapper는 기본적으로 같은 이름의 속성을 매핑하고 나머지는 하나씩 지정해야하며 Prop1.Ignore (), Prop2.Ignore () 등과 같은 작업을 수행해야합니다.

  • valueinjecter에는 이름과 유형이 같은 속성을 수행하는 기본 주입 .InjectFrom ()이 있습니다. 다른 모든 것에는 개별 매핑 로직 / 규칙을 사용하여 사용자 정의 값 인젝션을 만듭니다 (예 : Type Foo의 모든 소품에서 Bar의 모든 소품에 이르기까지)


5
사랑의 신을 위해 ValueInjector가 딥 그래프 ViewModel을 가져와 딥 그래프 비즈니스 엔터티와 매핑 할 수 있고 작업없이 정확히 똑같은 모든 것을 매핑 할 수 있으며 다른 것을 처리하는 방법 만 지정하면된다고 말해주십시오. AutoMapper 가이 기능을 추가하기를 희망했지만 실현되지 않았으며 자체 자동 매퍼를 작성할 시간이 없었습니다.
Chris Marisic

3
@Chris Marisic 당신은 그것을 사용할 수 있습니다, 당신이 깊은 복제를 의미하는 경우, 나는 한 번 주사를 한 번 반복했습니다.하지만 컬렉션 속성으로는 작동하지 않습니다 valueinjecter.codeplex.com/Thread/View.aspx?ThreadId=236126 또는 당신이 평면 뷰 모델을하고 평평하고 unflattening을 사용할 수 있습니다, 이것은 쉬운 것입니다
OMU

ViewModel과 도메인 엔터티는 비슷하지만 다르므로 순수한 클론은 아닙니다. 속성의 90 %는 일반적으로 정확한 유형과 이름이며, ViewModel은 종종 SelectLists로 끝나고 도메인에 다시 오는 것을 무시하고 싶은 것들이 있습니다. 둘 다 객체 컬렉션을 가질 가능성이 높습니다.
Chris Marisic 2012 년

27
<pedant>멋져 보이지만 아마도 ValueInjectOr이어야합니까? </pedant>
Craig Stuntz

1
그러나 어떤 이유로 그것은 잘못되었습니다 :)
Omu

59

다른 도구를 사용한 적이 없으므로 AutoMapper에 대해서만 이야기 할 수 있습니다. AutoMapper를 구축하기 위해 몇 가지 목표를 염두에 두었습니다.

  • 멍청한 DTO 객체로 평탄화 지원
  • 즉시 사용 가능한 명백한 시나리오 지원 (컬렉션, 열거 등)
  • 테스트에서 매핑을 쉽게 확인할 수 있습니다
  • 다른 위치 (사용자 지정 유형-> 유형 매핑, 개별 멤버 매핑 및 일부 미친 에지 사례)에서 값을 해결하기위한 에지 사례를 허용합니다.

이러한 작업을 수행하려는 경우 AutoMapper가 매우 효과적입니다. AutoMapper가 잘 수행하지 못하는 것은 다음과 같습니다.

  • 기존 객체 채우기
  • 펴지다

내가 이런 일을 할 필요가 없었던 이유. 대부분의 경우 엔터티에는 세터가 없으며 컬렉션을 노출하지 않는 등의 이유가 있습니다. AutoMapper를 사용하여 DTO로 평면화하고 UI 모델에서 명령 메시지 등에 매핑합니다. 그것이 우리에게 정말 잘 작동하는 곳입니다.


1
@Jimmy Bogard 기존 객체를 채우면 AutoMapper의 기능 목록에 해당 객체가 만들어 질 것입니까?
로마

나는 ValueInjecter를 시도하지 않았지만 우리가 필요로하는 것에 대해 automapper는 매우 강력합니다.
richb01

여기서 가장 중요한 것은 검증 가능성이라고 생각합니다. 이름을 바꾸고 리팩토링 할 때 큰 도움이됩니다.
Kugel

55

나는 두 가지를 모두 시도했고 ValueInjecter는 너무 간단하기 때문에 선호합니다.

myObject.InjectFrom(otherObject);

이것이 대부분의 주입 요구에 대해 알아야 할 모든 것입니다. 이보다 더 단순하고 우아하지는 않습니다.


1
this object확장 방법이 있습니까?
Chris Marisic

2
ValueInjecter에서 코드를 어떻게 분리 할 수 ​​있습니까? 주어진 객체에서 직접 ValueInjecter (확장 방법)를 사용하기 때문에 웹 프로젝트에서 항상 ValueInjecter에 대한 의존성을 가지고있는 것처럼 보입니다.
Rookian

1
@Rookian 솔직히 이것은 너무 많은 생각을 기울여야 할 문제가 아닙니다. @Omu와 같은 인터페이스에 의존 할 수 있으므로 매퍼를 변경하면 약간의 작업을 절약 할 수 있습니다. .NET이 AOP 지원을 올바르게 제공하지 못하기 때문에 불행히도 여러 번 실행 취소 할 수없는 완전 불완전 AOP에 들어가기를 원하지 않는 한 이러한 유형의 종속성은 추상화하기가 너무 어렵습니다. 이제 MVC를 사용하고 ViewModel / DomainModel 매핑을 처리하는 동작 필터를 작성하는 경우 일부 매핑을 AOP 할 수 있습니다.
Chris Marisic

13
래퍼가 왜 최상의 솔루션입니까? 매퍼를 전환하려면 InjectFrom()확장 프로그램을 직접 구현해야 합니다.
jgauffin

1
나는 둘 다 시도했지만 AutoMapper를 선호합니다. Linq2Sql 생성 클래스로 엔티티를 맵핑하는 시스템의 작은 부분에 사용했습니다. StockTotalQuantity-> stock_size_quantity 또는 UserId-> user_id와 같은 간단한 매핑은 기본적으로 AutoMapper와 함께 작동했습니다. 대류를 추가 한 후에도 ValeInjecter에서 작동하지 않았습니다. 지금은 AutoMapper를 고수합니다.
Artur Kędzior

27

이것은 내가 연구 한 질문이며, 유스 케이스의 경우 가치 인젝터가 손에 넣은 것 같습니다. 사용할 사전 설정이 필요하지 않습니다 (스마트하게 구현하면 매번 반영하기보다는 나중에 호출하기 위해 매핑을 캐시 할 수 있지만 성능을 떨어 뜨릴 수 있음). 매핑을 사용하기 전에 미리 정의 할 필요가 없습니다.

그러나 가장 중요한 것은 역 매핑을 허용합니다. 지미가 필요로하는 유스 케이스를 보지 못한다고 언급하면서 여기에 뭔가 빠져있을 수 있습니다. 그래서 패턴이 잘못되었을 수도 있지만 내 유스 케이스는 ORM에서 ViewModel 객체를 작성하는 것입니다. 그런 다음 웹 페이지에 이것을 표시합니다. 사용자가 완료하면 ViewModel을 httppost로 다시 가져 오는데 어떻게 원래 ORM 클래스로 다시 변환됩니까? automapper로 패턴을 알고 싶습니다. 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에 가치가없는 것으로 보입니까?)

그러나이 패턴이 규정 된대로 사용하려는 경우 내 투표는 국가 마일리지로 가치 인젝터입니다.


1
아마 당신은 asp.net-mvc 태그가 달린 별도의 질문과 ViewModel ..., atm 태그가있는 별도의 질문 으로이 질문을해야 할 것입니다. 누군가 다른 의견을 가질 수 있습니다
Omu

더 많은 mvc를 배웠습니다. 이제 내 질문에 대답 할 수 있습니다. 채워진 뷰 모델을 다시 가져올 때 원래 모델을 업데이트하는 방법은 mvc가 제공하는 UpdateModel () 함수를 사용하는 것입니다.
DanH

1
UpdateModel ()은 뷰를 나타내는 Model을 채우는데 사용되며 Action (MyModelClasss model)
Omu

사실이지만, 예를 들어 리포지토리 모델과 별도의 뷰 모델을 원한다면 매핑이 사소한 것으로 가정하고 채우는 데 사용할 수 있습니다. 물론 더 복잡한 ValueInjector가 자체적으로 제공된다면.
DanH 2016 년

1
도메인 모델에서 단순히 속성을 다시 설정해서는 안된다는 주장을 할 수 있다고 생각합니다. 의미를 더하는 메소드를 사용해야합니다.
Mike Cole
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.