Задать вопрос
ArXen42
@ArXen42

Как удобнее агрегировать события, оповещающие об изменении свойств?

Для примера, пусть будет корабль. Он состоит из отсеков. В отсеках может быть установлено какое-либо оборудование. У корабля есть масса, складываемая из массы всех его отсеков. Масса каждого отсека, например, зависит от того, установлено в него оборудование или нет. А масса самого оборудования также может меняться, например, зависеть от массы топлива в топливном баке. И вот об изменении своей массы каждый компонент из этой цепочки должен оповещать.

Для наглядности, сферическая иерархия классов:
public class Spacecraft
{
	public IEnumerable<Hardpoint> Hardpoints { get; private set; }

	public Single Mass => Hardpoints.Select(hp => hp.Mass).Sum();
}

public class Hardpoint
{
	public Equipment InstalledEquipment { get; private set; }

	public Boolean IsEquipmentInstalled => InstalledEquipment != null;

	public Single Mass => IsEquipmentInstalled ? InstalledEquipment.Mass : 0;
}

public abstract class Equipment
{
	public event Action MassChanged;

	public Single Mass
	{
		get { return _mass; }
		protected set
		{
			_mass = value;
			MassChanged?.Invoke();
		}
	}

	private Single _mass;
}

(сферичнее некуда)

Иными словами, есть дерево свойств (в данном случае Mass), каждое из которых зависит от своих потомков и свойство на любом из уровней должно уметь оповещать о своем изменении (т.е. вопрос в реализации MassChanged у Hardpoint и Spacecraft наименее затратным способом). Конечно, я могу просто сделать в Hardpoint событие MassChanged и вызывать его по аналогичному событию от установленного оборудования или при его смене. Также в Spacecraft. Очень много однотипного кода подписок/отписок, error-prone.
Другой вариант - нарушить инкапсуляцию и сделать invocator события в Hardpoint публичным, вызывая его при вызове сеттера массы вместе с вызовом своего события. Также сделать и со Spacecraft. Чуть меньше кода, но грязно.

Есть ли какие-нибудь более продвинутые практики?
  • Вопрос задан
  • 201 просмотр
Подписаться 2 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 2
Корабль в каждый момент времени имеет определенное состояние.
Что то может его изменять, и кто то должен быть подписан на эти изменения.
Flux -> Redux, можно позаимствовать реализацию.
Implementing Redux in C#

Или стандартные Интерфейс INotifyPropertyChanged.
Ответ написан
Комментировать
yarosroman
@yarosroman Куратор тега C#
C# the best
Возможно вам подойдет reactivex.io
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы