using System;
using System.Collections.Generic;
namespace Artemis.Core;
///
/// Provides a default implementation for models that can have a broken state
///
public abstract class BreakableModel : CorePropertyChanged, IBreakableModel
{
private string? _brokenState;
private Exception? _brokenStateException;
///
/// Invokes the event
///
protected virtual void OnBrokenStateChanged()
{
BrokenStateChanged?.Invoke(this, EventArgs.Empty);
}
///
public abstract string BrokenDisplayName { get; }
///
/// Gets or sets the broken state of this breakable model, if this model is not broken.
/// Note: If setting this manually you are also responsible for invoking
///
public string? BrokenState
{
get => _brokenState;
set => SetAndNotify(ref _brokenState, value);
}
///
/// Gets or sets the exception that caused the broken state
/// Note: If setting this manually you are also responsible for invoking
///
public Exception? BrokenStateException
{
get => _brokenStateException;
set => SetAndNotify(ref _brokenStateException, value);
}
///
public bool TryOrBreak(Action action, string breakMessage)
{
try
{
action();
ClearBrokenState(breakMessage);
return true;
}
catch (Exception e)
{
SetBrokenState(breakMessage, e);
return false;
}
}
///
public void SetBrokenState(string state, Exception? exception = null)
{
if (state == BrokenState && BrokenStateException?.StackTrace == exception?.StackTrace)
return;
BrokenState = state ?? throw new ArgumentNullException(nameof(state));
BrokenStateException = exception;
OnBrokenStateChanged();
}
///
public void ClearBrokenState(string state)
{
if (state == null)
throw new ArgumentNullException(nameof(state));
// If there was no broken state to begin with, done!
if (BrokenState == null)
return;
// Only clear similar broken states
if (BrokenState != state)
return;
BrokenState = null;
BrokenStateException = null;
OnBrokenStateChanged();
}
///
public virtual IEnumerable GetBrokenHierarchy()
{
if (BrokenState != null)
yield return this;
}
///
public event EventHandler? BrokenStateChanged;
}