从父对象获取派生属性的数据

时间:2018-08-03 03:48:50

标签: c# asp.net-core automapper

我有两个用户对象,学生和教授。每个用户可以有自己的设置,如下所示:

public class PersonSettings
{
    public Guid Id { get; set; }
    public Guid PersonId { get; set; }
    public PersonSettingsValues Settings { get; set; }
}

public class PersonSettingsValues
{
    public bool NotificationsEnabled { get; set; }
}

public class StudentSettingsValues : PersonSettingsValues
{
    public int GymPassTypeId { get; set; }
}

public class ProfessorSettingsValues : PersonSettingsValues
{
    public bool AllowOfficeHours { get; set; }
}

某些设置是共享的,但是学生和教授也有自己的设置,因此我继承了模型。

我只是通过使用PersonSettings上的转换值将设置作为json存储在数据库中:

builder.Property(ps => ps.Settings).HasConversion(
    s => JsonConvert.SerializeObject(s, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }),
    s => JsonConvert.DeserializeObject<PersonSettingsValues>(s, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));

因此,PersonSettings表中填充了几条带有设置的记录,有些记录的“设置”列中的数据格式设置为“ StudentSettings”,而另一些则是“ ProfessorSettings”

我想做的是有一个端点,该端点将为学生返回StudentSettings。我有:

[HttpGet("{personId}")]
public async Task<IActionResult> GetStudentSettings([FromRoute] Guid personId)
{
    var personSettings = await _context.PersonSettings
        .FirstOrDefaultAsync(ps => ps.PersonId == id);

    return Ok(personSettings);
}

问题在于,Settings属性仅填充了PersonSettingsValues,而我没有获得StudentSettingsValues。我不确定如何做到这一点。

我尝试改用DTO并通过AutoMapper映射到它:

public class StudentSettingsDTO
{
    public Guid Id { get; set; }
    public Guid PersonId { get; set; }
    public StudentSettingsValues Settings { get; set; }
}

...

[HttpGet("{personId}")]
public async Task<IActionResult> GetStudentSettings([FromRoute] Guid personId)
{
    var personSettings = await _context.PersonSettings
        .FirstOrDefaultAsync(ps => ps.PersonId == id);

    return Ok(_mapper.Map<StudentSettingsDTO>(personSettings));
}

...

CreateMap<PersonSettings, StudentSettingsDTO>()
    .ForMember(ps => ps.Settings,
        o => o.ResolveUsing(s => (StudentSettingsValues)s.Settings));

在映射中,我只是尝试将“设置”转换为StudentSettingsValues类型,但出现错误提示

  

无法将“ PersonSettingsValues”类型的对象强制转换为“ StudentSettingsValues”类型

不知道我在这里做错了什么,如何才能返回上面带有StudentSettings或ProfessorSettings的PersonSettings对象?

1 个答案:

答案 0 :(得分:1)

这是因为您的构建器在从数据库解析json时会解析为PersonSettingsValues。一旦完成,您将丢失所有其他数据。您有几种选择:

  1. 不确定此构建器到底是什么以及您有多少自定义逻辑 可以添加。但是,如果在反序列化时知道 教授或学生,您应该反序列化所需的对象。 然后,即使将其分配给PersonSettingsValues,您也​​仍然可以 以后可以将其转换为更具体的类型。
  2. 创建界面,而不是使用不同的模型。 IPersonSettingsValues, IStudentSettingsValues和IProfessorSettingsValues。然后有 只是实现所有接口的一种模型。那你的 解串器可以序列化到那个模型。没有的值 存在将默认使用,但始终会反序列化。和 那么当您想从特定上下文使用它时,您将能够 将其投射到特定的界面。
  3. 反序列化为动态对象(因此仅反序列化json中的内容),然后使用autoMapper将动态对象映射为具体类型。

如果不清楚,请告诉我,我将尝试提出一个代码示例。