JsonSerializer.Deserialize把字符串反序列化给类实例,类中的监测变量变化事件不在产生事件?

国栋 刘 0 信誉分
2025-03-28T04:30:38.6333333+00:00

你好!

在我的应用里,使用了System.Text.Json里的反序列化,类实例接受反序列化结果后,类中监测变量改变的事件将不会触发,我用其它代码实现反序列化,事件就会正常触发。是我使用的问题还是这里面存在Bug?

谢谢你的帮助!

C#用户

2025-3-28

                    remote_io = JsonSerializer.Deserialize<MyClass>(str); //使用这行出问题,用下面三行替换就正常

                    //string[] substr = str.Split(new char[2] { ':', ',' });   

                    //remote_io.output = substr[3].Substring(1, 8); ;

                    //remote_io.input = substr[5].Substring(1, 8); ;
以下是部分相关的代码:

       

 public Form1()
    {

        //CheckForIllegalCrossThreadCalls = false;//为在其它纯种中可调用窗体控件

        //如果为Ture;可用this.BeginInvoke(new Action(delegate (){}));//在线程里刷新UI界面

        InitializeComponent();

        remote_io = new MyClass();

        remote_io.output = "00000000";

        remote_io.OnMyValueChanged += myclase_OnMyValueChanged;

    }
类中变量改变监测事件

void myclase_OnMyValueChanged(object sender, EventArgs e)
 {

     //当变量值发生变化的时候,执行

     if (remote_io.OUT1) btOUT1.BackColor = Color.Green;

     else btOUT1.BackColor = Color.Red;
 }
   }


    private void btConnect_Click(object sender, EventArgs e)

    {

        cts = new CancellationTokenSource();

        threadClient = new Thread(() =>

        {

            IPEndPoint ipendpoint = new IPEndPoint(IPAddress.Any, 8998);

            while (!cts.IsCancellationRequested)

            {

                try

                {

                    if (udpclient.Available <= 0) { Thread.Sleep(100); continue; }//判断是否有网络数据

                    if (udpclient.Client == null) return;//判断连接是否为空

                                                         //调用UdpClient对象的Receive方法获得从远程主机返回的UDP数据报

                    byte[] bytes = udpclient.Receive(ref ipendpoint);

                    //将获得的UDP数据报转换为字符串形式

                    string str = Encoding.Default.GetString(bytes);   //返回格式:{"cmd":"setr","output":"10111111","input":"00000000","humidity":43.8,"centigrade":26.5,"fahrenheit":79.70,"runtime":1303,"timestamp":0,"sn":"V59f09ad589e9719"}

                    remote_io = JsonSerializer.Deserialize<MyClass>(str); //使用这行出问题,用下面三行替换就正常

                    //string[] substr = str.Split(new char[2] { ':', ',' });   

                    //remote_io.output = substr[3].Substring(1, 8); ;

                    //remote_io.input = substr[5].Substring(1, 8); ;

                    this.BeginInvoke(new Action(delegate ()

                    {   // }));//在线程里刷新UI界面

                        rtbRecive.Text += "\n" + str;//显示接收的所有数据  

                                                     //JSON反序列化

                        rtbRecive.Text += "\nIO输出:" + remote_io.output;//显示接收的所有数据  

                        rtbRecive.Text += "\n湿度:" + remote_io.humidity;//显示接收的所有数据  

                        rtbRecive.Text += "\n温度" + remote_io.centigrade;//显示接收的所有数据  

                        rtbRecive.Text += "\nOUT1:" + remote_io.OUT1;//显示接收的所有数据  

                        rtbRecive.Text += "\nIN1:" + remote_io.IN1;//显示接收的所有数据  

                    }));//在线程里刷新UI界面

                }

                catch (Exception ex)

                {

                    MessageBox.Show(ex.Message);//错误提示

                }

            }

        });

        threadClient.IsBackground = true;

        rtbRecive.Clear();

        threadClient.Start();

        rtbRecive.AppendText("客户端接收已经开启");

        btConnect.Enabled = false;

     }
接收到的数据格式

json
{"cmd":"setr","output":"10111111","input":"00000000","humidity":43.8,"centigrade":26.5,"fahrenheit":79.70,"runtime":1303,"timestamp":0,"sn":"V59f09ad589e9719"}
接收反序列化的类


class MyClass
{
   private string _input;

    public string input

    { get=>_input;

        set

        {

            _input = value;

            IN1 = _input[0] == '1' ? true : false;

            IN2 = _input[1] == '1' ? true : false;

            // 触发事件

            //OnMyValueChanged?.Invoke(this, OUT1);

            WhenMyValueChange();

        }

    }

    。。。。

    //定义的委托

    public delegate void MyValueChanged(object sender, EventArgs e);

    //与委托相关联的事件

    public event MyValueChanged OnMyValueChanged;

     //事件触发函数

    private void WhenMyValueChange()

    {

        if (OnMyValueChanged != null)

        {

            OnMyValueChanged(this, null);

        }

    }
}
(完)
.NET
.NET
基于 .NET 软件框架的 Microsoft 技术。
94 个问题
0 个注释 无注释
{count} 票

3 个答案

排序依据: 非常有帮助
  1. 匿名
    2025-03-28T14:19:13.2966667+00:00

    System.Text.Json 反序列化时 不会调用属性的 setter,导致事件不触发。

    尝试在 OnDeserialized 事件后手动触发 setter。

    using System.Text.Json;
    using System.Text.Json.Serialization;
    
    class MyClass
    {
        private string _input;
    
        public string input
        {
            get => _input;
            set
            {
                _input = value;
                IN1 = _input[0] == '1';
                IN2 = _input[1] == '1';
                WhenMyValueChange();
            }
        }
    
        public bool IN1 { get; private set; }
        public bool IN2 { get; private set; }
    
        public event EventHandler OnMyValueChanged;
    
        private void WhenMyValueChange()
        {
            OnMyValueChanged?.Invoke(this, EventArgs.Empty);
        }
    
        [JsonConstructor]
        public MyClass(string input)
        {
            this.input = input; // 调用 setter 以触发事件
        }
    
        public MyClass() { } // 需要无参构造函数
    }
    

    如果答案是正确的,请点击“接受答案”并点赞。 如果您对此答案还有其他疑问,请点击“评论”。

    注意:如果您想接收相关电子邮件,请按照我们的文档中的步骤启用电子邮件通知 此线程的通知。

    0 个注释 无注释

  2. 国栋 刘 0 信誉分
    2025-04-08T14:36:26.25+00:00

    你的回答并没有解决了我的问题,我不明白的是:

    标记了[JsonConstructor] 的构造函数,在JSON反序列号时,会被自动调用吗?

    [JsonConstructor] 不是用于给只读属性的成员变量赋值吗?

    我之前的程序,反序列化后,类的成员变量值已经改变了,也就是set程序段被执行了,但是同在set程序段的触发事件却不执行

    0 个注释 无注释

  3. 国栋 刘 0 信誉分
    2025-04-09T04:15:45.0333333+00:00

    我的理解是:反序列化时,实际是生成了一个新的实例,把新的实例指针直接赋给了原先的实例,这样就没有属性变化事件发生了

    0 个注释 无注释

你的答案

问题作者可以将答案标记为“接受的答案”,这有助于用户了解已解决作者问题的答案。