using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; using FluentResults; namespace InABox.Core { public interface ILinkedProperty { Type Type { get; } String Path { get; } String Source { get; } String Target { get; } void Update(object from, object to); /// /// This equality comparer checks against type, path, source and target /// /// /// bool Equals(object obj); } public class LinkedProperty : ILinkedProperty where TLinkedEntity : class where TEntityLink : class { public Type Type => typeof(TLinkedEntity); public String Path { get; } private Func _source; public String Source { get; } public String Target { get; } private readonly Func>? _func; public override string ToString() { return $"{Type.EntityName().Split('.').Last()}: {Path}{(String.IsNullOrWhiteSpace(Path) ? "" : ".")}{Source} => {Target}"; } public LinkedProperty(Expression> path, Expression> source, Expression> target, Func>? func = null) { Path = CoreUtils.GetFullPropertyName(path, "."); Source = CoreUtils.GetFullPropertyName(source, "."); Target = CoreUtils.GetFullPropertyName(target,"."); _func = func; _source = source.Compile(); } public void Update(object from, object to) { if (from is TEntityLink fromLink && to is TLinkedEntity toEntity) { var value = _source.Invoke(fromLink); //var value = CoreUtils.GetPropertyValue(from, Source); if (_func != null) { var result = _func(toEntity, value); if (!result.Get(out value, out var _)) return; } CoreUtils.SetPropertyValue(to, Target, value); } } public override bool Equals(object obj) { if (obj is ILinkedProperty src) { return (obj as ILinkedProperty).Type == Type && String.Equals(src.Path,Path) && String.Equals(src.Source, Source) && String.Equals(src.Target, Target); } return false; } } }