using System; using System.Dynamic; using System.Linq; namespace InABox.Core { public interface IEntityLink { 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(); //[Obsolete("Please supply linked Entity")] public EntityLink() { } public EntityLink(Func? entity) { _linkedentity = entity; } [NullEditor] public abstract Guid ID { get; set; } [NullEditor] public Guid Deleted { get; set; } 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)); } } } } } } var le = LinkedEntity(); if (le != null) foreach (var link in LinkedProperties.Find(le,this)) { link.Update(this, le); 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) { var le = LinkedEntity(); if (IsObserving() && le != null) { var link = LinkedProperties.Find(le, this).FirstOrDefault(x => x.Source.Equals(name)); if (link != null) link.Update(this, le); } } public bool IsValid() => !ID.Equals(Guid.Empty) && Deleted.Equals(Guid.Empty); } }