具有属性的类,可以是两种不同类型之一

时间:2015-08-05 09:49:05

标签: c# class telegram-bot

我正在用C#开发一个Telegram机器人,但是在实现Message类型时遇到了困难。根据{{​​3}},chat字段可以是User类型,也可以是GroupChat类型。我如何在C#中实现它?

到目前为止,我只能使用Newtonsoft.Json

来提供以下代码
public class Update {
....
  [JsonProperty("chat")]
  public User chat { get; set; }

  [JsonProperty("chat")]
  public GroupChat group_chat { get; set; }
....
}

但它不适用于我的WebAPI 2控制器方法,因为我使用Message属性反序列化FromBody

public async Task<HttpResponseMessage> Post(string token, [FromBody] Update update)

(类型Update的字段message类型为Message

有没有更好的方法来实现Message类型?

3 个答案:

答案 0 :(得分:2)

由于您应该在一个字段中处理看似两个完全不同的对象,我不认为您可以使用强类型对象,但您可以在聊天字段中使用动态类型,例如

public class Telegram
{
    public int message_id { get; set; }
    public dynamic chat { get; set; }
}

然后,您可以访问变量并检查它们是否为空,以了解它是用户还是群组聊天:

static void Main(string[] args)
{
    string json = @"{ ""chat"": { ""id"": 1, ""first_name"": ""my_first_name"", ""last_name"": ""my_last_name"",  ""username"": ""my_username"" }, ""message_id"": 123 }";
    var telegram = Newtonsoft.Json.JsonConvert.DeserializeObject<Telegram>(json);
    string name = telegram.chat.first_name; // name = my_first_name
    string title = telegram.chat.title; // title = null
}

答案 1 :(得分:0)

我也在Java中遇到过这个问题。由于C#和Java都是强类型语言,我的问题类似。 我通过创建一个通用的Chat类来解决这个问题。此Chat类包含User以及GroupChat中的属性。该课程还包含方法isUser()isGroupChat()asUser()asGroupChat()

我必须承认我不了解C#,所以我不能为你编写那种语言的例子,但这里是Chat类的主体,用Java:

@SerializedName("id")
private int id;

@SerializedName("first_name")
private String firstName;

@SerializedName("last_name")
private String lastName;

@SerializedName("username")
private String username;

@SerializedName("title")
private String title;

public boolean isUser() {
    return title == null;
}

public boolean isGroupChat() {
    return !isUser();
}

public User asUser() {
    return new User(id, firstName, username, lastName);
}

public GroupChat asGroupChat() {
    return new GroupChat(id, title);
}

它非常冗长并且添加了重复的代码,所以如果有人有任何补充,我也希望听到它们。

答案 2 :(得分:0)

您可以将Message类型构建为界面(IMessage),然后使用GroupMessageUserMessage类来实现它。

interface IMessage
{
   int id;

   //...

   object chat {get;}
}

public class GroupMessage : IMessage
{
   public int id;
   public GroupChat group;
   public object chat {get {return group;} }
}

public class UserMessage : IMessage
{
   public int id;
   public User user;
   public object chat {get {return user;} }
}

但我真正要做的是在更高的层次处理这个问题。看一下这里的文档,而不是一个可以处理所有这些的复杂对象,我会考虑发送接收一条消息。然后我会想到您在收到邮件时可能想要做的所有操作。从那里我将有一个对象可以为每个动作引发事件。当您收到数据(不要将其视为消息)时,您解析数据并可能从一个Telegram消息对象中引发多个事件。其中一些事件可能需要事件所需数据的类定义,但现在我们谈论的范围要窄得多;更适合单一责任原则。

走向另一个方向(发送数据而不是接收),该对象将具有您在发送数据时可能执行的各种操作的方法。其中一些方法可能需要所需数据的类。如果可能,请使用您为接收事件所执行的相同类。它甚至可能只是一个带有很多重载的Send()方法。