每次我在StackOverflow上寻找AutoMapper的东西,我都在阅读有关valueinjector的东西。

谁能告诉我它们之间的优缺点(性能、特性、API使用、可扩展性、测试)?


作为valueinjector的创建者,我可以告诉你,我这样做是因为我想要一些简单而灵活的东西

我真的不喜欢写太多或者写很多猴子代码,比如:

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

valueinjector有点像mozilla的插件,你创建valueinjection并使用它们

有一些内置的注入用于变平、变平,还有一些是打算被继承的

它以一种方面类型的方式工作,你不必1对1地指定所有属性,相反,你可以这样做:

从source中获取所有以“Id”结尾的int属性,转换值并将每个属性设置为源对象中具有相同名称但没有Id后缀的属性,它的类型从Entity继承,诸如此类

一个明显的区别是,valueinjector甚至在窗口表单中使用,有扁平化和不扁平化,这就是它的灵活性

(从对象映射到窗体控件并返回)

Automapper,不能在windows窗体中使用,没有unflatenning,但它有像集合映射这样的好东西,所以如果你需要它与valueinjector,你只需要做这样的事情:

foo。Select(o => new Bar().InjectFrom(o));

你也可以使用valueinjector来映射匿名对象和动态对象

差异:

automapper create configuration for each mapping possibility CreateMap() valueinjecter inject from any object to any object (there are also cases when you inject from object to valuetype) automapper has flattening built it, and only for simple types or from same type, and it doesn't has unflattening valueinjecter only if you need it you do target.InjectFrom<FlatLoopValueInjection>(source); also <UnflatLoopValueInjection> and if you want from Foo.Bar.Name of type String to FooBarName of type Class1 you inherit FlatLoopValueInjection and specify this automapper maps properties with same name by default and for the rest you have to specify one by one, and do stuff like Prop1.Ignore(), Prop2.Ignore() etc. valueinjecter has a default injection .InjectFrom() that does the properties with the same name and type; for everything else you create your custom valueinjections with individual mapping logic/rules, more like aspects, e.g. from all props of Type Foo to all props of type Bar


我都试过了,更喜欢valueinjector,因为它太简单了:

myObject.InjectFrom(otherObject);

这就是我需要知道的绝大多数注射需求。没有比这更简单优雅的了。


由于我从未使用过其他工具,我只能谈谈AutoMapper。在构建AutoMapper时,我有几个目标:

支持扁平化到哑DTO对象 支持开箱即用的明显场景(集合、枚举等) 能够在测试中轻松地验证映射 允许使用边缘情况来解析来自其他地方的值(自定义类型->类型映射、单个成员映射和一些非常疯狂的边缘情况)。

如果你想做这些事情,AutoMapper非常适合你。AutoMapper做得不好的事情有:

填充现有对象 Unflattening

原因是我从来不需要做这些事情。在大多数情况下,我们的实体没有setter,不公开集合,等等,这就是它不存在的原因。我们使用AutoMapper将图形化到dto,并从UI模型映射到命令消息等。这对我们来说非常非常有效。


这也是我一直在研究的一个问题,对于我的用例来说,它似乎是价值注入器。它不需要事先设置即可使用(我猜可能会影响性能,不过如果巧妙地实现,它可以为将来的调用缓存映射,而不是每次都反射),因此在使用任何映射之前不需要预先定义它们。

Most importantly however, it allows reverse mapping. Now I may be missing something here as Jimmy mentions that he sees no use case where its necessary, so maybe I have the pattern wrong, but my use case is that I'm creating a ViewModel object from my ORM. I then display this on my webpage. Once the user finishes I get the ViewModel back in as a httppost, how does this get converted back to the original ORM classes? I'd love to know the pattern with automapper. With ValueInjector it is trivial, and it will even unflatten. e.g Creating a new entity

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

然而,如果你想使用描述的模式,那么我的投票是价值注入器。