using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using FluentResults; namespace InABox.Core { public interface ISubObject { BaseObject GetLinkedParent(); void SetLinkedParent(BaseObject obj); string GetLinkedPath(); void SetLinkedPath(string path); } // public interface IResult // { // object? Value { get; set; } // bool Cancel { get; set; } // } // // public class Result : IResult // { // public TType Value { get; set; } // // object? IResult.Value { // get => this.Value; // set => this.Value = (value is TType _type ? _type : default)!; // } // // public bool Cancel { get; set; } // // public Result(TType value, bool cancel = false) // { // Value = value; // Cancel = cancel; // } // } public static class LinkedProperties { private static readonly Dictionary> _LinkedProperties = new Dictionary>(); public static void Register(Expression> path, Expression> source, Expression> target, Func>? func = null) where TLinkedEntity : class where TEntityLink : class { var map = new LinkedProperty(path, source, target, func); if(!_LinkedProperties.TryGetValue(map.Type, out var props)) { props = new List(); _LinkedProperties[map.Type] = props; } if(!props.Any(x => x.Equals(map))) { props.Add(map); } } /*public static IEnumerable Find(object parent, object path) { var all = _LinkedProperties.Where(x => x.Type == parent.GetType()); var filtered = all.Where(x => CoreUtils.GetPropertyValue(parent,x.Path)?.GetType() == path?.GetType()); return filtered; }*/ private static BaseObject GetParent(ISubObject link) { while (true) { var parent = link.GetLinkedParent(); if(parent is IEntityLink parentLink) { link = parentLink; } else { return parent; } } } private static string GetPath(ISubObject link) { var path = link.GetLinkedPath(); while (true) { var parent = link.GetLinkedParent(); if (parent is IEntityLink parentLink) { link = parentLink; path = $"{link.GetLinkedPath()}.{path}"; } else { return path; } } } public static IEnumerable FindAll(Type parent) { if (_LinkedProperties.TryGetValue(parent, out var props)) { return props; } return Enumerable.Empty(); } public static IEnumerable Find(ISubObject subObject, out BaseObject parent) { parent = GetParent(subObject); if (!_LinkedProperties.TryGetValue(parent.GetType(), out var props)) { return Enumerable.Empty(); } var path = GetPath(subObject); return props.Where(x => x.Path == path); } public static bool Find(ISubObject subObject, string name, [NotNullWhen(true)] out ILinkedProperty? property, out BaseObject parent) { property = null; parent = GetParent(subObject); if (parent == null) return false; if(!_LinkedProperties.TryGetValue(parent.GetType(), out var props)) return false; var path = GetPath(subObject); property = props.FirstOrDefault(x => String.Equals($"{x.Path}{(String.IsNullOrWhiteSpace(x.Path) ? "" : ".")}{x.Source}", $"{path}{(String.IsNullOrWhiteSpace(path) ? "" : ".")}{name}")); return property != null; } } }