C#: наблюдение за переменной другого класса

225
23 октября 2017, 23:03

Классический пример: класс Lamp , описывающий электрическую лампочку, с состояниями On (bool on = true) и Off (bool on = false). Я хочу отслеживать значения этой переменной из другого класса (например, LightingControl), чтобы этот класс реагировал на изменения состояния лампочки. Из класса Lamp не могут быть вызываны никакие методы других классов, так как класс Lamp является моделью непрограммируемого электрического прибора. Как это реализовать?

Заготовка кода для ответа:

class Lamp(){
    public bool on;
    public Lamp(bool onOrOffSignal){
        this.on = onOrOffSignal;
    }
    // ... 
}
class LightingControl(){
    Lamp lamp = new Lamp();
    // ... 
    // это реагирование должно происходить в режиме реального времни
    if (Lamp.on == true){
        emergencyLighting.turnOff();
    }
    else {
        emergencyLighting.turnOn(); 
    }
}
Answer 1

INotifyPropertyChanged, он должен быть известен вам по экспериментам с WPF:

class Program
{
    static void Main(string[] args)
    {
        Lamp lamp = new Lamp();
        LightingControl lc = new LightingControl(lamp);
        lamp.IsOn = true;
        lamp.IsOn = false;
        Console.ReadKey();
    }
}
class Lamp : INotifyPropertyChanged
{
    bool isOn;
    public bool IsOn
    {
        get => isOn;
        set
        {
            isOn = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsOn)));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}
class LightingControl
{
    Lamp _lamp;
    public LightingControl(Lamp lamp)
    {
        _lamp = lamp;
        lamp.PropertyChanged += OnLampPropertyChanged;
    }
    private void OnLampPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(Lamp.IsOn))
        {
            Console.WriteLine($"Lamp {(_lamp.IsOn ? "On" : "Off")}!");
        }
    }
}

Связанный вопрос: Как организовать взаимодействие объекта с его наблюдателем

Answer 2

Для таких случаев были придуманы события:

private bool _on;
public bool on {
  get { return _on; }
  set { _ob = value; StatusChanged?.Invoke(this, EventArgs.Empty); }
}
public event EventHandler StatusChanged;

Также существует стандартный интерфейс INotifyPropertyChanged, который умеют понимать стандартные редакторы свойств в дизайнерах WinForms и WPF, а также дата-биндинги там же:

public class Lamp : INotifyPropertyChanged {
  private bool _on;
  public bool on {
    get { return _on; }
    set { _ob = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("on")); }
  }
  public event PropertyChangedEventHandler PropertyChanged;
}

Для более сложных случаев можно использовать Reactive Extensions.NET.

READ ALSO
Реализация своего AutoMapper. C#

Реализация своего AutoMapper. C#

Я использую в своем учебном проекте AutoMapper, но мне он кажется неудобным инструментомЯ сделал свою функцию для конвертации данных из ViewModel...

220
Передача файла в контроллер

Передача файла в контроллер

Не приходят данные на контроллер

192
Не удалось найти тип или имя пространства имен Unit

Не удалось найти тип или имя пространства имен Unit

Помогите решить проблему, пожалуйстаВ unity работаю совсем не долго, как решать подобное?

273
lock объекта по Id

lock объекта по Id

Столкнулся со следующей проблемойИмеется некий метод,записывающий сущность в бд, примерно такой:

206