【问题标题】:AutoMapper figure out inheritance when mapping from C# Dynamic/ExpandoObjectAutoMapper 从 C# Dynamic/ExpandoObject 映射时找出继承
【发布时间】:2021-09-17 13:59:20
【问题描述】:

我有一个问题,我正在尝试使用 AutoMapper 将来自数据库(为了清楚起见是 MongoDB,但我认为这无关紧要)的动态对象映射到特定类。

类继承信息存储在属性_t中(由Mongo在序列化时完成)-在创建包含继承的基础对象时,如何指示AutoMapper使用_t中的类信息?

这是我的班级信息

class Person
{
public string id { get; set; }
public Foo Foo { get; set; }
}
class Foo
{
public string name { get; set; }
public string _t { get; set; }
}
class Bar : Foo
{
public string size { get; set; }
}

我传入的动态对象如下所示:

Person.id = "Bob"
Person.Foo.name = "Bob"
Person.Foo._t = "Bar"
Person.Foo.size = "123"

当我使用 automapper 使用此代码将其映射到 Person 时

        var configuration = new MapperConfiguration(cfg => {});
        var mapper = configuration.CreateMapper();
        Person Person = mapper.Map<Person>(MyDynamic);

生成的 Person.Foo 不是 Bar 类型。我完全理解(为什么)会出现这种情况,因为 AutoMapper 不了解原始类是什么。但是考虑到类的信息存储在 _t 中,我可以指示 AutoMapper 使用它来确保 Person.Foo 是 Bar 类型吗?

【问题讨论】:

    标签: c# dynamic automapper expandoobject


    【解决方案1】:

    您可以通过以下方式实现它:

    dynamic person = new ExpandoObject();
    
    person.Foo = new ExpandoObject();
    person.Foo.name = "Bob";
    person.Foo._t = "Bar";
    person.Foo.size = "123";
    
    var configuration = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<dynamic, Person>().ConvertUsing((src, dst, ctx) =>
        {
            if (src.Foo._t == "Foo")
            {
                return new Person
                {
                    Foo = ctx.Mapper.Map<Foo>(src.Foo)
                };
            }
            else
            {
                return new Person
                {
                    Foo = ctx.Mapper.Map<Bar>(src.Foo)
                };
            }
        });
    });
    
    var mapper = configuration.CreateMapper();
    Person p = mapper.Map<Person>(person);
    

    注意:如果Foonull,上述示例不处理这种情况,但应该适用于您在问题中概述的确切问题。

    【讨论】:

    • 这会让我走上正确的道路(我认为),但问题是 Person 类实际上还有另一个属性(我已经编辑了我的原始帖子以显示这一点),所以我不能做一个返回新的人,我也需要在人中映射属性。
    • 我尝试映射继承的类,但尝试执行此操作时出现堆栈溢出:cfg.CreateMap().ConvertUsing((src, dst, ctx) => { if (src._t == "Bar") { return ctx.Mapper.Map(src); } else { return null; } });
    • 您知道自动映射器是否可以在映射父对象之前先映射对象中的子对象?我尝试使用 CreateMap 对 Foo 映射子类型,但在这种情况下,Foo 永远不会包含 Bar 的属性。试图找到正确映射 Bar 的方法,同时维护父 Person 对象的属性。
    猜你喜欢
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多