将接口派生类与NEST和ElasticSearch一起使用

时间:2016-04-12 16:15:48

标签: c# .net elasticsearch interface nest

我尝试使用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.

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

非常感谢!

-Z

1 个答案:

答案 0 :(得分:1)

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

Per @ MartijnLaarman的建议我在Roles属性中添加了[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属性现在提供List中每个元素的完整类型描述符。

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