|
@@ -1,4 +1,5 @@
|
|
|
using System;
|
|
|
+using System.Collections;
|
|
|
using System.Collections.Concurrent;
|
|
|
using System.Collections.Generic;
|
|
|
using System.ComponentModel;
|
|
@@ -26,6 +27,83 @@ namespace InABox.Core
|
|
|
public void SetObserving(bool active);
|
|
|
}
|
|
|
|
|
|
+ public interface IOriginalValues : IEnumerable<KeyValuePair<string, object?>>
|
|
|
+ {
|
|
|
+ public object? this[string key] { get; set; }
|
|
|
+
|
|
|
+ public bool ContainsKey(string key);
|
|
|
+
|
|
|
+ public void Clear();
|
|
|
+
|
|
|
+ public bool TryGetValue(string key, out object? value);
|
|
|
+
|
|
|
+ public bool TryAdd(string key, object? value);
|
|
|
+
|
|
|
+ public void Remove(string key);
|
|
|
+
|
|
|
+ public object? GetValueOrDefault(string key)
|
|
|
+ {
|
|
|
+ if(TryGetValue(key, out object? value)) return value;
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public class OriginalValues : IOriginalValues
|
|
|
+ {
|
|
|
+ private readonly ConcurrentDictionary<string, object?> Dictionary = new ConcurrentDictionary<string, object?>();
|
|
|
+
|
|
|
+ public object? this[string key] { get => Dictionary[key]; set => Dictionary[key] = value; }
|
|
|
+
|
|
|
+ public void Clear()
|
|
|
+ {
|
|
|
+ Dictionary.Clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool ContainsKey(string key) => Dictionary.ContainsKey(key);
|
|
|
+
|
|
|
+ public IEnumerator<KeyValuePair<string, object?>> GetEnumerator()
|
|
|
+ {
|
|
|
+ return Dictionary.GetEnumerator();
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool TryGetValue(string key, out object? value)
|
|
|
+ {
|
|
|
+ return Dictionary.TryGetValue(key, out value);
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool TryAdd(string key, object? value)
|
|
|
+ {
|
|
|
+ return Dictionary.TryAdd(key, value);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Remove(string key)
|
|
|
+ {
|
|
|
+ (Dictionary as IDictionary<string, object?>).Remove(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
|
+ }
|
|
|
+
|
|
|
+ public interface ILoadedColumns
|
|
|
+ {
|
|
|
+ public bool Add(string key);
|
|
|
+
|
|
|
+ public bool Contains(string key);
|
|
|
+ }
|
|
|
+ public class LoadedColumns : ILoadedColumns
|
|
|
+ {
|
|
|
+ private HashSet<string> Columns = new HashSet<string>();
|
|
|
+
|
|
|
+ public bool Add(string key)
|
|
|
+ {
|
|
|
+ return Columns.Add(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool Contains(string key)
|
|
|
+ {
|
|
|
+ return Columns.Contains(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Observable object with INotifyPropertyChanged implemented
|
|
|
/// </summary>
|
|
@@ -57,9 +135,7 @@ namespace InABox.Core
|
|
|
|
|
|
protected virtual void Init()
|
|
|
{
|
|
|
- CheckOriginalValues();
|
|
|
-
|
|
|
- LoadedColumns = new HashSet<string>();
|
|
|
+ LoadedColumns = CreateLoadedColumns();
|
|
|
|
|
|
UserProperties = new UserProperties();
|
|
|
//UserProperties.ParentType = this.GetType();
|
|
@@ -85,7 +161,7 @@ namespace InABox.Core
|
|
|
|
|
|
public static bool GlobalObserving = true;
|
|
|
|
|
|
- private bool _observing = true;
|
|
|
+ private bool _observing = false;
|
|
|
|
|
|
public bool IsObserving()
|
|
|
{
|
|
@@ -111,11 +187,19 @@ namespace InABox.Core
|
|
|
private bool bChanged;
|
|
|
|
|
|
[DoNotPersist]
|
|
|
- public ConcurrentDictionary<string, object?> OriginalValues { get; set; }
|
|
|
+ private IOriginalValues _originalValues;
|
|
|
+ public IOriginalValues OriginalValues
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ _originalValues ??= CreateOriginalValues();
|
|
|
+ return _originalValues;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
[DoNotPersist]
|
|
|
[DoNotSerialize]
|
|
|
- public HashSet<string> LoadedColumns { get; set; }
|
|
|
+ public ILoadedColumns LoadedColumns { get; set; }
|
|
|
|
|
|
protected virtual void SetChanged(string name, object? before, object? after)
|
|
|
{
|
|
@@ -140,11 +224,15 @@ namespace InABox.Core
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // This function is *only* meant to be called by EnclosedEntity and EntityLink
|
|
|
+ internal void CascadePropertyChanged(string name, object? before, object? after)
|
|
|
+ {
|
|
|
+ SetChanged(name, before, after);
|
|
|
+ }
|
|
|
|
|
|
private bool QueryChanged()
|
|
|
{
|
|
|
- CheckOriginalValues();
|
|
|
- if (OriginalValues.Count > 0)
|
|
|
+ if (OriginalValues.Any())
|
|
|
return true;
|
|
|
|
|
|
foreach (var oo in DatabaseSchema.GetSubObjects(this))
|
|
@@ -173,21 +261,18 @@ namespace InABox.Core
|
|
|
if (!BaseObjectExtensions.HasChanged(before, after))
|
|
|
return;
|
|
|
|
|
|
- CheckOriginalValues();
|
|
|
if (!OriginalValues.ContainsKey(name))
|
|
|
OriginalValues[name] = before;
|
|
|
SetChanged(name, before, after);
|
|
|
}
|
|
|
|
|
|
- private void CheckOriginalValues()
|
|
|
+ protected virtual IOriginalValues CreateOriginalValues()
|
|
|
{
|
|
|
- if (OriginalValues == null)
|
|
|
- {
|
|
|
- var bObserving = _observing;
|
|
|
- _observing = false;
|
|
|
- OriginalValues = new ConcurrentDictionary<string, object?>();
|
|
|
- _observing = bObserving;
|
|
|
- }
|
|
|
+ return new OriginalValues();
|
|
|
+ }
|
|
|
+ protected virtual ILoadedColumns CreateLoadedColumns()
|
|
|
+ {
|
|
|
+ return new LoadedColumns();
|
|
|
}
|
|
|
|
|
|
public bool IsChanged()
|
|
@@ -201,13 +286,12 @@ namespace InABox.Core
|
|
|
var bObs = IsObserving();
|
|
|
SetObserving(false);
|
|
|
|
|
|
- CheckOriginalValues();
|
|
|
- foreach (var key in OriginalValues.Keys.ToArray())
|
|
|
+ foreach (var (key, value) in OriginalValues)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
var prop = key.Contains(".")
|
|
|
- ? CoreUtils.GetProperty(GetType(),key)
|
|
|
+ ? CoreUtils.GetProperty(GetType(), key)
|
|
|
: GetType().GetRuntimeProperty(key);
|
|
|
if(prop != null)
|
|
|
{
|
|
@@ -222,7 +306,7 @@ namespace InABox.Core
|
|
|
}
|
|
|
else if (UserProperties.ContainsKey(key))
|
|
|
{
|
|
|
- UserProperties[key] = OriginalValues[key];
|
|
|
+ UserProperties[key] = value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -251,7 +335,6 @@ namespace InABox.Core
|
|
|
{
|
|
|
bApplyingChanges = true;
|
|
|
|
|
|
- CheckOriginalValues();
|
|
|
OriginalValues.Clear();
|
|
|
|
|
|
bChanged = false;
|
|
@@ -268,8 +351,7 @@ namespace InABox.Core
|
|
|
var type = GetType();
|
|
|
try
|
|
|
{
|
|
|
- CheckOriginalValues();
|
|
|
- foreach (var key in OriginalValues.Keys)
|
|
|
+ foreach (var (key, _) in OriginalValues)
|
|
|
try
|
|
|
{
|
|
|
if (UserProperties.ContainsKey(key))
|