让 2 类 在 C# 中相互通信的最佳方法

Best aproach to let 2 classes communicate with each other in C#

我对 OOP 和 C# 比较陌生,想问一下让两个 classes 使用彼此的方法的“最佳实践”是什么。

示例:我有一个“Main Class”,它实例化了一个 Class“UI”,它管理与触摸屏的通信和一个 class与外部传感器通信的“传感器”。

当有人按下显示器上的按钮时,UI Class 中会触发一个事件。作为反应,需要调用来自传感器 Class 的“ReadSensor”方法。 (反过来,“SensorDataCallback”需要向显示器写入内容)。

现在在 C++ 中,我会把两个 Class 对象设为全局对象,但在 C# 中没有这个选项。 我尝试将 Methodes 添加到 Class 中,它接受对各自其他 class 实例的引用并存储它们,但这似乎不是最好的方法。我的另一种方法是将 class 都设置为静态,因为只有一个显示器和一个传感器,但我猜这也不是最好的方法。

Sketch

有人可以给我提示吗?

我不建议将两个 class 彼此如此紧密地联系在一起,实际上你最终会得到循环引用。

尝试让您的 classes 独立,以便保持明确的关注点分离。

因此,传感器 class 仅处理检索传感器数据和发出新值通知(如果要定期或异步自动读取值)。

你的 UI class 只处理显示和对用户输入的反应。

您的 Main class 充当两者之间的数据处理程序。

UI 显示代码通知 Main class 用户请求信息; Main class 处理此问题并触发 Sensor class 以检索新的传感器值。

The Sensor class notifies/passes 新的传感器值到主 class; main class 然后通知 UI 有一个新值可用。

因此传感器不需要知道显示器,显示器也不需要知道传感器。

以上内容符合当前使用 MVVM (Model-View-ViewModel) 结构的 C# 程序和用户界面的“最佳实践”。在这种情况下,您的视图是显示器,ViewModel 是您的主要 class,模型是您的传感器 class。

在这种安排中,View class 使用数据绑定从 ViewModel 检索传感器值。 View 将在按下 ViewModel 作出反应的按钮时引发事件(可能绑定到命令),触发它请求来自传感器的更新数据。传感器将该数据提供给 ViewModel,当它更新其传感器值时 属性 会引发 属性 已更改的通知,触发 View 更新。

这是 WPF 应用程序中 MVVM 的一个非常基本的示例。我没有包括整个项目,只是基本的 classes:

查看:(MainWindow.xaml)

<Window x:Class="SimpleWPF.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SimpleWPF"
    mc:Ignorable="d"
    Title="MainWindow" Height="204.673" Width="219.626">
<Window.DataContext>
    <local:MainViewModel/>
</Window.DataContext>
<Grid>
    <TextBox x:Name="textBox" Text="{Binding SensorValue, Mode=OneWay }" HorizontalAlignment="Left" Height="23" Margin="38,47,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
    <Button x:Name="button" Command="{Binding ReadSensorCommand}" Content="Read" HorizontalAlignment="Left" Margin="62,94,0,0" VerticalAlignment="Top" Width="75"/>

</Grid>

带有助手的 ViewModel (MainViewMode.cs) class:

public class MainViewModel :INotifyPropertyChanged
{
    public MainViewModel()
    {
        ReadSensorCommand = new RelayCommand(new Action<object>(ReadFreshSensorData));
    }
    private ICommand _ReadSensorCommand;
    private int _sensorValue;
    private readonly SensorModel _sensor = new SensorModel();

    private void ReadFreshSensorData(object o)
    {
        SensorValue =_sensor.ReadSensor();
    }
    public int SensorValue
    {
        get=>_sensorValue;
        private set
        {
            _sensorValue = value;
            OnPropertyChanged(nameof(SensorValue));
        }
    }

    public ICommand ReadSensorCommand
    {
        get => _ReadSensorCommand;
        set => _ReadSensorCommand = value;
    }
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
class RelayCommand : ICommand
{
    private readonly Action<object> _action;

    public RelayCommand(Action<object> action)
    {
        _action = action;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _action(parameter ?? "");
    }
}

最后模型 (SensorModel.cs)

public class SensorModel
{
    private Random _rnd = new Random();

    public int ReadSensor()
    {
        return _rnd.Next(1000);
    }
}

诚然,这仅演示了用户触发了传感器读取,但 SensorModel 可以在其接口上有一个事件 属性,而 MainViewModel 有一个处理程序。然后 SensorModel 可以调用事件以将值传递给 MainViewModel,MainViewModel 然后从事件处理程序更新 SensorValue。