将派生接口 类 与 NEST 和 ElasticSearch 结合使用

Using Interface Derived Classes with NEST and ElasticSearch

我正在尝试使用 NEST 2.X 和 Elastic Search 来持久存储用户。每个用户都包含一个角色列表,这些角色定义了他们在我们平台内的权限。

有几种不同类型的角色,每一种都派生自 IMediaDetectionRole 接口:

public class MediaDetectionUser
{
    public string Username { get; set; }
    public ICollection<IMediaDetectionRole> Roles { get; set; }

    public MediaDetectionUser()
    {
        Roles = new List<IMediaDetectionRole>();
    }
}

public interface IMediaDetectionRole
{
    string Name { get; }
    string GetDescription();
    string GetRoleType {get;}
}

[ElasticsearchType(Name="MediaDetectionAdminRole")]
public class MediaDetectionAdminRole : IMediaDetectionRole
{        
    public string Name { get { return "Admin"; } }
    public string GetDescription() { return "Admin users can create other users within the account"; }
    public string GetRoleType { get { return this.GetType().Name; } }
}

[ElasticsearchType(Name = "MediaDetectionManagerRole")]
public class MediaDetectionManagerRole : IMediaDetectionRole
{
    public string Name { get { return "Manager"; } }
    public string GetDescription() { return "Managers can modify account-level properties"; }
    public string GetRoleType { get { return this.GetType().Name; } }
}

[ElasticsearchType(Name = "MediaDetectionCreatorRole")]
public class MediaDetectionCreatorRole : IMediaDetectionRole
{
    public string Name { get { return "Creator"; } }
    public string GetDescription() { return "Creators can create new Media Detection Profiles"; }
    public string GetRoleType { get { return this.GetType().Name; } }
}

我在ElasticSearch 中存储数据没有任何问题,但是当我去查询数据时,数据NEST 无法确定这些角色的类型。我得到:

Could not create an instance of type IMediaDetectionRole. 
Type is an interface or abstract class and cannot be instantiated. 
Path 'hits.hits[0]._source.roles[0].name', line 1, position 343.

将嵌套对象数据映射回正确的 class 类型的正确方法是什么?

非常感谢!

-Z

好吧,所以我想这不是一个 NEST/ES 问题,而是一个 JSON.NET 问题。显然,这个问题的解决方案涉及告诉 JSON.NET 为列表的每个成员提供类型提示。

根据@MartijnLaarman 的建议,我向角色 属性 添加了一个 [JsonProperty] 属性。见下文:

public class MediaDetectionUser
{
    public string Username { get; set; }

    //This JsonProperty helps reference the types during deserialization
    [JsonProperty("Roles", ItemTypeNameHandling = TypeNameHandling.All)]
    public ICollection<IMediaDetectionRole> Roles { get; set; }

    public MediaDetectionUser()
    {
        Roles = new List<IMediaDetectionRole>();
    }
}

这里有一个 JSON 的例子,它出现在 ElasticSearch 的 _source 中:

Roles: [
  {
    $type: "MediaDetectionFrontend.ServiceModel.Types.MediaDetectionAdminRole, MediaDetectionFrontend.ServiceModel",
    name: "Admin",
    getRoleType: "MediaDetectionAdminRole"
  },
  {
    $type: "MediaDetectionFrontend.ServiceModel.Types.MediaDetectionCreatorRole, MediaDetectionFrontend.ServiceModel",
    name: "Creator",
    getRoleType: "MediaDetectionCreatorRole"
  },
  {
    $type: "MediaDetectionFrontend.ServiceModel.Types.MediaDetectionEditorRole, MediaDetectionFrontend.ServiceModel",
    name: "Editor",
    getRoleType: "MediaDetectionEditorRole"
  }
]

您可以看到 $type 属性现在提供了列表中每个元素的完整类型描述符。

非常感谢@MartijnLaarman 帮助我解决了这个问题,尽管它确实与 ElasticSearch 和 NEST 无关。