using Expressive; using System; using System.Dynamic; using System.Linq; namespace InABox.Core { public interface IEntityLink : ISubObject { Guid ID { get; set; } Guid Deleted { get; set; } bool Synchronise(object entity); bool Clear(); bool IsValid(); } public interface IEntityLink : IEntityLink { } public abstract class EntityLink : BaseObject, IEntityLink where T : BaseObject, new() { /* private Func? _linkedentity; [DoNotSerialize] protected BaseObject? LinkedEntity() => _linkedentity?.Invoke();*/ private BaseObject _linkedParent; private string _linkedPath; public void SetLinkedParent(BaseObject parent) { _linkedParent = parent; } public void SetLinkedPath(string path) { _linkedPath = path; } public BaseObject GetLinkedParent() => _linkedParent; public string GetLinkedPath() => _linkedPath; /* [Obsolete("Please supply linked Entity")] public EntityLink() { } public EntityLink(Func? entity, string name) { _linkedentity = entity; }*/ [NullEditor] public abstract Guid ID { get; set; } [NullEditor] [Obsolete] public Guid Deleted { get; set; } /// /// Basically do the same as , but also copy the . /// /// The link to copy data from. public void CopyFrom(IEntityLink other) { ID = other.ID; Synchronise(other); } public virtual bool Synchronise(object Entity) { var result = false; var props = CoreUtils.PropertyList(GetType(), x => (!x.Name.Equals("ID") || Entity == null) && !x.DeclaringType.Equals(typeof(BaseObject)), false); foreach (var key in props.Keys) { if (CoreUtils.HasProperty(Entity.GetType(), key)) { var prop = CoreUtils.GetProperty(typeof(T), key); if (prop != null && prop.PropertyType.Equals(props[key])) { if (prop.PropertyType.GetInterfaces().Any(x => x == typeof(IEntityLink))) { var tgtlink = CoreUtils.GetPropertyValue(this, key) as IEntityLink; var srclink = CoreUtils.GetPropertyValue(Entity, key) as IEntityLink; tgtlink.ID = srclink.ID; tgtlink.Synchronise(srclink); } else { var oldvalue = CoreUtils.GetPropertyValue(this, key); var newvalue = CoreUtils.GetPropertyValue(Entity, key); if ((oldvalue == null && newvalue != null) || (oldvalue != null && !oldvalue.Equals(newvalue))) { result = true; try { CoreUtils.SetPropertyValue(this, key, newvalue); } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } } } } } } foreach (var link in LinkedProperties.Find(this, out var parent)) { link.Update(this, parent); result = true; } return result; } public bool Clear() { var result = false; var props = CoreUtils.PropertyList(GetType(), x => !x.Name.Equals("ID"), false); foreach (var key in props.Keys) { var prop = CoreUtils.GetProperty(typeof(T), key); if (prop != null && prop.PropertyType.Equals(props[key])) { var oldvalue = CoreUtils.GetPropertyValue(this, key); var newvalue = prop.PropertyType.Equals(typeof(string)) ? "" : Activator.CreateInstance(prop.PropertyType); if ((oldvalue == null && newvalue != null) || (oldvalue != null && !oldvalue.Equals(newvalue))) { result = true; CoreUtils.SetPropertyValue(this, key, newvalue); } } } return result; } protected override void DoPropertyChanged(string name, object? before, object? after) { if (IsObserving()) { if(LinkedProperties.Find(this, name, out var link, out var parent)) { link.Update(this, parent); } } } public bool IsValid() => !ID.Equals(Guid.Empty) && Deleted.Equals(Guid.Empty); } }