C# AutoMapper vs ValueInjector

C# AutoMapper vs ValueInjector,c#,.net,automapper,valueinjecter,object-object-mapping,C#,.net,Automapper,Valueinjecter,Object Object Mapping,每次我在StackOverflow上查找内容时,我都会读到一些关于 谁能告诉我它们之间的优缺点(性能、功能、API使用、可扩展性、测试)?作为的创建者,我可以告诉你,我这样做是因为我想要一些简单且非常灵活的东西 我真的不喜欢写太多或写太多的monkey代码,比如: Prop1.Ignore, Prop2.Ignore etc. CreateMap<Foo,Bar>(); CreateMap<Tomato, Potato>(); etc. Prop1.Ignore、Pro

每次我在StackOverflow上查找内容时,我都会读到一些关于

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

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

我真的不喜欢写太多或写太多的
monkey代码
,比如:

Prop1.Ignore, Prop2.Ignore etc.
CreateMap<Foo,Bar>(); CreateMap<Tomato, Potato>(); etc.
Prop1.Ignore、Prop2.Ignore等。
CreateMap();CreateMap();等
ValueInjector是一种类似mozilla的插件,您可以创建ValueInjections并使用它们

有用于平坦化、去平坦化的内置注入,还有一些是用于继承的

而且它在方面类型方面更有效,您不必以1对1的方式指定所有属性,而是执行如下操作:

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

一个明显的区别是,ValueInjector即使在具有平坦化和非平坦化的windows窗体中也可以使用,这就是它的灵活性

(从对象到窗体控件的映射以及从窗体控件到窗体控件的映射)

Automapper,在windows窗体中不可用,没有解冻功能,但它具有集合映射之类的功能,因此,如果您需要ValueInjector,只需执行以下操作:

foos.Select(o=>newbar().InjectFrom(o))

您还可以使用ValueInjector从匿名对象和动态对象进行映射

差异:

  • 自动映射为每个映射创建配置可能性CreateMap()

  • valueinjecter从任何对象注入到任何对象(也有从对象注入到valuetype的情况)

  • automapper有“展平”功能,仅适用于简单类型或同一类型,没有“展平”功能

  • ValueInjector,仅当您需要它时才执行
    target.InjectFrom(源代码);另外
    如果要从类型字符串的
    Foo.Bar.Name
    到类型Class1的
    FooBarName
    继承FlatLoopValueInjection并指定此

  • 默认情况下,automapper映射具有相同名称的属性,对于其他属性,您必须逐个指定,并执行诸如Prop1.Ignore()、Prop2.Ignore()等操作

  • ValueInjector有一个默认的injection.InjectFrom(),它处理具有相同名称和类型的属性;对于其他所有内容,您可以使用单独的映射逻辑/规则创建自定义ValueInjection,更像方面,例如从Foo类型的所有道具到Bar类型的所有道具


我尝试了这两种方法,更喜欢ValueInjector,因为它非常简单:

myObject.InjectFrom(otherObject);

这就是我绝大多数注射需要知道的。再简单不过了,再优雅不过了

因为我从未使用过任何其他工具,所以我只能谈论AutoMapper。构建AutoMapper时,我有几个目标:

  • 支持展平到哑DTO对象
  • 支持开箱即用的明显场景(集合、枚举等)
  • 能够在测试中轻松验证映射
  • 允许从其他位置解析值的边缘情况(自定义类型->类型映射、单个成员映射和一些非常疯狂的边缘情况)
如果你想做这些事情,AutoMapper非常适合你。AutoMapper做得不好的事情有:

  • 填充现有对象
  • 松懈

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

这也是我一直在研究的一个问题,对于我的用例来说,它似乎是ValueInjector。它不需要预先设置就可以使用(我想可能会影响性能,尽管如果巧妙地实现,它可以缓存映射以供将来调用,而不是每次都进行反射),因此在使用映射之前不需要预定义任何映射

然而,最重要的是,它允许反向映射。现在我可能遗漏了一些东西,因为Jimmy提到他没有看到任何必要的用例,所以可能我的模式有误,但我的用例是我正在从ORM创建一个ViewModel对象。然后我在我的网页上显示这个。用户完成后,我将ViewModel作为httppost返回,如何将其转换回原始ORM类?我想知道automapper的模式。有了ValueInjector,它是微不足道的,甚至会变得毫无意义。e、 g创建新实体

entityframework创建的模型(模型优先):

ViewModel(我可以用验证器装饰):

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();
        }
    }
//
//获取:/Family/Create
公共操作结果创建()
{
返回视图();
} 
//
//POST:/Family/创建
[HttpPost]
公共操作结果创建(FamilyViewModel FamilyViewModel)
{
尝试
{
家族=新家族();
family.InjectFrom(familyViewModel);
db.Families.Add(family);
db.SaveChanges();
返回操作(“索引”);
}
抓住
{
返回视图();
}
}
在我看来,没有比这更简单的了

(因此,这就引出了一个问题,我遇到的这种模式(似乎许多其他人也这么做了)有什么问题,它对AutoMapper没有价值?)

但是,如果您想使用所描述的模式,那么我的投票是以国家英里为单位的ValueInjector。

另一个是我的投票
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; }
}
    //
    // 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();
        }
    }