简体   繁体   English

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

[英]Class with property that can be one of two different types

I'm developing a Telegram bot in C# but have difficulty with implementing Message type. 我正在用C#开发一个Telegram bot,但是在实现Message类型时遇到了困难。 According to API documentation , chat field can be either of type User or of type GroupChat . 根据API文档chat字段可以是User类型或GroupChat类型。 How do I implement that in C#? 我如何在C#中实现它?

So far I could only come up with following code using Newtonsoft.Json : 到目前为止,我只能使用Newtonsoft.Json提出以下代码:

public class Update {
....
  [JsonProperty("chat")]
  public User chat { get; set; }

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

But it doesn't work with my WebAPI 2 controller method since I deserialize Message using FromBody attribute: 但它不适用于我的WebAPI 2控制器方法,因为我使用FromBody属性反序列化Message

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

(type Update has a field message of type Message ) (类型Update有一个Message类型的字段message

Is there any better way to implement Message type? 有没有更好的方法来实现Message类型?

Since you are supposed to handle seemingly two completely different objects in one field I don't think you can use strongly-typed objects but you can use a dynamic type for the chat field such as 由于您应该在一个字段中处理看似两个完全不同的对象,我认为您不能使用强类型对象,但您可以使用动态类型作为聊天字段,例如

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

Then you can access the variables and check if they are null or not to understand if it's a user or a group chat: 然后,您可以访问变量并检查它们是否为空,以了解它是用户还是群聊:

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
}

I have faced this issue in Java as well. 我也在Java中遇到过这个问题。 As both C# and Java are strong typed languages, my issue was similar. 由于C#和Java都是强类型语言,我的问题类似。 I solved this by creating a generic Chat class. 我通过创建一个通用的Chat类来解决这个问题。 This Chat class contains the properties from User as well as from GroupChat . Chat类包含UserGroupChat The class also has the methods isUser() , isGroupChat() , asUser() and asGroupChat() . 该类还具有方法isUser()isGroupChat()asUser()asGroupChat()

I have to admit I have no knowledge of C#, so I can not write an example in that language for you, but here is the body of the Chat class, in Java: 我不得不承认我不了解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);
}

It's quite verbose and adds duplicate code, so if anyone has any additions, I'd like to hear them as well. 它非常冗长,并添加了重复的代码,所以如果有人有任何补充,我也想听听它们。

You could build your Message type as an interface ( IMessage ), and then implement it with GroupMessage and UserMessage classes. 您可以将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;} }
}

But what I would really do is handle this at a higher level. 但我真正要做的是在更高的层次上处理这个问题。 Looking at the docs here, rather than a complex object that can handle all of this I would think in terms of sending or receiving a message. 看一下这里的文档,而不是一个可以处理所有这些的复杂对象,我会考虑发送接收消息。 Then I would think of all of the actions you might want to do when receiving a message. 然后我会考虑接收消息时您可能想要做的所有操作 From there I would have an object that can raise an event for each of those actions. 从那里我将有一个对象可以为每个动作引发一个事件 When you receive data (don't think of it as a message), you parse the data and perhaps raise several events from what was one Telegram message object. 当您收到数据 (不要将其视为消息)时,您解析数据并可能从一个Telegram消息对象中引发多个事件。 Some of those events may require class definitions for the data needed by the event, but now we're talking something that's much narrower in scope; 其中一些事件可能需要事件所需数据的类定义,但现在我们谈论的范围要窄得多; a better fit for the Single Responsibility Principle. 更适合单一责任原则。

Going the other direction (sending data rather than receiving), the object would have methods for the different kinds of things you might do when sending data. 走向另一个方向(发送数据而不是接收),该对象将具有用于在发送数据时可能执行的各种事物的方法。 Some of those methods may require classes for the data needed. 其中一些方法可能需要所需数据的类。 When possible, use the same classes you did for the receiving events. 如果可能,请使用您为接收事件所执行的相同类。 It might even be just one Send() method with many overloads. 它甚至可能只是一个带有许多重载的Send()方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 构建一个类以将json反序列化为一个属性可以是两种不同类型时 - Building a class to deserialize json to when one properties can be of two different types 如何将两种不同的XML类型反序列化为一个类 - How to deserialize two different XML types in to one class 将数据从一个类实例复制到另一个具有相同属性名称但不同属性类型的类实例 - Copy data from one class instance to another class instance having same property names but different property types 如何处理 json 字段,它可以是两种不同类型之一? - How to handle a json field, which can be one of two different types? AutoMapper合并两种类型忽略一个属性 - AutoMapper Merge Two Types Ignoring one property 在 C# 中,我可以声明一个属性,以便它只能返回两种类型之一 - In C#, can I declare a property so that it can return just one of two types 如何使用 Json.NET 反序列化可以是两种不同数据类型的 JSON 属性 - How to deserialize a JSON property that can be two different data types using Json.NET AutoMapper,将一种类型映射到两种不同的类型 - AutoMapper, mapping one type in two different types 尝试将两种不同的类型映射到一个值 - Trying to map two different types to one value 反序列化可以具有不同类型的属性名称 - Deserialize a property name that can have different types
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM