mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 19:36:28 +00:00
Data model events - WIP commit
This commit is contained in:
1 parent
b8112601df
commit
03b0e83ed8
19 files changed
+554
-28
No files matched your search
@@ -13,20 +13,30 @@ namespace Artemis.Core
|
||||
/// <param name="a">The parameter on the left side of the expression</param>
|
||||
/// <param name="b">The parameter on the right side of the expression</param>
|
||||
public abstract bool Evaluate(TLeftSide a, TRightSide b);
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
internal override bool InternalEvaluate(object? leftSideValue, object? rightSideValue)
|
||||
{
|
||||
// TODO: Can we avoid boxing/unboxing?
|
||||
TLeftSide leftSide;
|
||||
if (leftSideValue != null)
|
||||
leftSide = (TLeftSide) Convert.ChangeType(leftSideValue, typeof(TLeftSide));
|
||||
{
|
||||
if (leftSideValue.GetType() != typeof(TLeftSide))
|
||||
leftSide = (TLeftSide) Convert.ChangeType(leftSideValue, typeof(TLeftSide));
|
||||
else
|
||||
leftSide = (TLeftSide) leftSideValue;
|
||||
}
|
||||
else
|
||||
leftSide = default;
|
||||
|
||||
TRightSide rightSide;
|
||||
if (rightSideValue != null)
|
||||
rightSide = (TRightSide) Convert.ChangeType(rightSideValue, typeof(TRightSide));
|
||||
{
|
||||
if (rightSideValue.GetType() != typeof(TRightSide))
|
||||
rightSide = (TRightSide) Convert.ChangeType(rightSideValue, typeof(TRightSide));
|
||||
else
|
||||
rightSide = (TRightSide) rightSideValue;
|
||||
}
|
||||
else
|
||||
rightSide = default;
|
||||
|
||||
@@ -57,7 +67,12 @@ namespace Artemis.Core
|
||||
// TODO: Can we avoid boxing/unboxing?
|
||||
TLeftSide leftSide;
|
||||
if (leftSideValue != null)
|
||||
leftSide = (TLeftSide) Convert.ChangeType(leftSideValue, typeof(TLeftSide));
|
||||
{
|
||||
if (leftSideValue.GetType() != typeof(TLeftSide))
|
||||
leftSide = (TLeftSide)Convert.ChangeType(leftSideValue, typeof(TLeftSide));
|
||||
else
|
||||
leftSide = (TLeftSide)leftSideValue;
|
||||
}
|
||||
else
|
||||
leftSide = default;
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// A condition that evaluates to true when an event is triggered
|
||||
/// </summary>
|
||||
public class DataModelConditionEvent : DataModelConditionPart
|
||||
{
|
||||
private bool _disposed;
|
||||
private bool _reinitializing;
|
||||
private IDataModelEvent? _event;
|
||||
private bool _eventTriggered;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataModelConditionEvent" /> class
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
public DataModelConditionEvent(DataModelConditionPart parent)
|
||||
{
|
||||
Parent = parent;
|
||||
Entity = new DataModelConditionEventEntity();
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
internal DataModelConditionEvent(DataModelConditionPart parent, DataModelConditionEventEntity entity)
|
||||
{
|
||||
Parent = parent;
|
||||
Entity = entity;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path of the event property
|
||||
/// </summary>
|
||||
public DataModelPath? EventPath { get; private set; }
|
||||
|
||||
|
||||
internal DataModelConditionEventEntity Entity { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Evaluate()
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("DataModelConditionEvent");
|
||||
|
||||
// Ensure the event has not been replaced
|
||||
if (EventPath?.GetValue() is IDataModelEvent dataModelEvent && _event != dataModelEvent)
|
||||
SubscribeToDataModelEvent(dataModelEvent);
|
||||
|
||||
// Only evaluate to true once every time the event has been triggered
|
||||
if (!_eventTriggered)
|
||||
return false;
|
||||
|
||||
_eventTriggered = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SubscribeToDataModelEvent(IDataModelEvent dataModelEvent)
|
||||
{
|
||||
if (_event != null)
|
||||
_event.EventTriggered -= OnEventTriggered;
|
||||
|
||||
_event = dataModelEvent;
|
||||
if (_event != null)
|
||||
_event.EventTriggered += OnEventTriggered;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the event the condition is triggered by
|
||||
/// </summary>
|
||||
public void UpdateEvent(DataModelPath? path)
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("DataModelConditionEvent");
|
||||
|
||||
if (path != null && !path.IsValid)
|
||||
throw new ArtemisCoreException("Cannot update event to an invalid path");
|
||||
|
||||
EventPath?.Dispose();
|
||||
EventPath = path != null ? new DataModelPath(path) : null;
|
||||
SubscribeToEventPath();
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_disposed = true;
|
||||
|
||||
EventPath?.Dispose();
|
||||
|
||||
foreach (DataModelConditionPart child in Children)
|
||||
child.Dispose();
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal override bool EvaluateObject(object target)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override void Save()
|
||||
{
|
||||
// Don't save an invalid state
|
||||
if (EventPath != null && !EventPath.IsValid)
|
||||
return;
|
||||
|
||||
// Target list
|
||||
EventPath?.Save();
|
||||
Entity.EventPath = EventPath?.Entity;
|
||||
}
|
||||
|
||||
internal override DataModelConditionPartEntity GetEntity()
|
||||
{
|
||||
return Entity;
|
||||
}
|
||||
|
||||
internal void Initialize()
|
||||
{
|
||||
if (Entity.EventPath == null)
|
||||
return;
|
||||
|
||||
// Ensure the list path is valid and points to a list
|
||||
DataModelPath eventPath = new DataModelPath(null, Entity.EventPath);
|
||||
// Can't check this on an invalid list, if it becomes valid later lets hope for the best
|
||||
if (eventPath.IsValid && !PointsToEvent(eventPath))
|
||||
return;
|
||||
|
||||
EventPath = eventPath;
|
||||
SubscribeToEventPath();
|
||||
}
|
||||
|
||||
private bool PointsToEvent(DataModelPath dataModelPath)
|
||||
{
|
||||
Type? type = dataModelPath.GetPropertyType();
|
||||
if (type == null)
|
||||
return false;
|
||||
|
||||
return typeof(IDataModelEvent).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
private void SubscribeToEventPath()
|
||||
{
|
||||
if (EventPath == null) return;
|
||||
EventPath.PathValidated += EventPathOnPathValidated;
|
||||
EventPath.PathInvalidated += EventPathOnPathInvalidated;
|
||||
}
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void OnEventTriggered(object? sender, EventArgs e)
|
||||
{
|
||||
_eventTriggered = true;
|
||||
}
|
||||
|
||||
private void EventPathOnPathValidated(object? sender, EventArgs e)
|
||||
{
|
||||
if (_reinitializing)
|
||||
return;
|
||||
|
||||
_reinitializing = true;
|
||||
EventPath?.Dispose();
|
||||
Initialize();
|
||||
_reinitializing = false;
|
||||
}
|
||||
|
||||
private void EventPathOnPathInvalidated(object? sender, EventArgs e)
|
||||
{
|
||||
if (_reinitializing)
|
||||
return;
|
||||
|
||||
_reinitializing = true;
|
||||
EventPath?.Dispose();
|
||||
Initialize();
|
||||
_reinitializing = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -180,7 +180,7 @@ namespace Artemis.Core
|
||||
DataModelPath listPath = new DataModelPath(null, Entity.ListPath);
|
||||
Type listType = listPath.GetPropertyType()!;
|
||||
// Can't check this on an invalid list, if it becomes valid later lets hope for the best
|
||||
if (listPath.IsValid && !listPath.PointsToList)
|
||||
if (listPath.IsValid && !PointsToList(listPath))
|
||||
return;
|
||||
|
||||
ListPath = listPath;
|
||||
@@ -208,6 +208,12 @@ namespace Artemis.Core
|
||||
}
|
||||
}
|
||||
|
||||
private bool PointsToList(DataModelPath dataModelPath)
|
||||
{
|
||||
Type? type = dataModelPath.GetPropertyType();
|
||||
return type?.IsGenericEnumerable() ?? false;
|
||||
}
|
||||
|
||||
private void SubscribeToListPath()
|
||||
{
|
||||
if (ListPath == null) return;
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using Artemis.Core.DataModelExpansions;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a data model event with event arguments of type <typeparamref name="T" />
|
||||
/// </summary>
|
||||
public class DataModelEvent<T> : IDataModelEvent where T : DataModelEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Trigger the event with the given <paramref name="eventArgs" />
|
||||
/// </summary>
|
||||
/// <param name="eventArgs">The event argument to pass to the event</param>
|
||||
public void Trigger(T eventArgs)
|
||||
{
|
||||
if (eventArgs == null) throw new ArgumentNullException(nameof(eventArgs));
|
||||
eventArgs.TriggerTime = DateTime.Now;
|
||||
|
||||
LastEventArguments = eventArgs;
|
||||
LastTrigger = DateTime.Now;
|
||||
TriggerCount++;
|
||||
|
||||
OnEventTriggered();
|
||||
}
|
||||
|
||||
internal virtual void OnEventTriggered()
|
||||
{
|
||||
EventTriggered?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public DateTime LastTrigger { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int TriggerCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the event arguments of the last time the event was triggered
|
||||
/// </summary>
|
||||
public T? LastEventArguments { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataModelIgnore]
|
||||
public Type ArgumentsType => typeof(T);
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? EventTriggered;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a data model event without event arguments
|
||||
/// </summary>
|
||||
public class DataModelEvent : IDataModelEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Trigger the event
|
||||
/// </summary>
|
||||
public void Trigger()
|
||||
{
|
||||
LastTrigger = DateTime.Now;
|
||||
TriggerCount++;
|
||||
|
||||
OnEventTriggered();
|
||||
}
|
||||
|
||||
internal virtual void OnEventTriggered()
|
||||
{
|
||||
EventTriggered?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public DateTime LastTrigger { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int TriggerCount { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataModelIgnore]
|
||||
public Type? ArgumentsType => null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? EventTriggered;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the base class for data model events that contain event data
|
||||
/// </summary>
|
||||
public class DataModelEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the time at which the event with these arguments was triggered
|
||||
/// </summary>
|
||||
public DateTime TriggerTime { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -111,18 +111,6 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<DataModelPathSegment> Segments => _segments.ToList().AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether this data model path points to a list
|
||||
/// </summary>
|
||||
public bool PointsToList
|
||||
{
|
||||
get
|
||||
{
|
||||
Type? type = GetPropertyType();
|
||||
return type?.IsGenericEnumerable() ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
internal DataModelPathEntity Entity { get; }
|
||||
|
||||
internal Func<object, object>? Accessor { get; private set; }
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
internal interface IDataModelEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the last time the event was triggered
|
||||
/// </summary>
|
||||
DateTime LastTrigger { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the amount of times the event was triggered
|
||||
/// </summary>
|
||||
int TriggerCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of arguments this event contains
|
||||
/// </summary>
|
||||
Type? ArgumentsType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Fires when the event is triggered
|
||||
/// </summary>
|
||||
event EventHandler EventTriggered;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user