LinkedProperties.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics.CodeAnalysis;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. namespace InABox.Core
  7. {
  8. public interface ISubObject
  9. {
  10. BaseObject GetLinkedParent();
  11. void SetLinkedParent(BaseObject obj);
  12. string GetLinkedPath();
  13. void SetLinkedPath(string path);
  14. }
  15. // public interface IResult
  16. // {
  17. // object? Value { get; set; }
  18. // bool Cancel { get; set; }
  19. // }
  20. //
  21. // public class Result<TType> : IResult
  22. // {
  23. // public TType Value { get; set; }
  24. //
  25. // object? IResult.Value {
  26. // get => this.Value;
  27. // set => this.Value = (value is TType _type ? _type : default)!;
  28. // }
  29. //
  30. // public bool Cancel { get; set; }
  31. //
  32. // public Result(TType value, bool cancel = false)
  33. // {
  34. // Value = value;
  35. // Cancel = cancel;
  36. // }
  37. // }
  38. public static class LinkedProperties
  39. {
  40. private static readonly Dictionary<Type, List<ILinkedProperty>> _LinkedProperties = new Dictionary<Type, List<ILinkedProperty>>();
  41. public static void Register<TLinkedEntity, TEntityLink, TType>(Expression<Func<TLinkedEntity,TEntityLink>> path, Expression<Func<TEntityLink, TType>> source,
  42. Expression<Func<TLinkedEntity, TType>> target, Func<TLinkedEntity,TType, Result<TType, string>>? func = null)
  43. where TLinkedEntity : class
  44. where TEntityLink : class
  45. {
  46. var map = new LinkedProperty<TLinkedEntity, TEntityLink, TType>(path, source, target, func);
  47. if(!_LinkedProperties.TryGetValue(map.Type, out var props))
  48. {
  49. props = new List<ILinkedProperty>();
  50. _LinkedProperties[map.Type] = props;
  51. }
  52. if(!props.Any(x => x.Equals(map)))
  53. {
  54. props.Add(map);
  55. }
  56. }
  57. /*public static IEnumerable<ILinkedProperty> Find(object parent, object path)
  58. {
  59. var all = _LinkedProperties.Where(x => x.Type == parent.GetType());
  60. var filtered = all.Where(x => CoreUtils.GetPropertyValue(parent,x.Path)?.GetType() == path?.GetType());
  61. return filtered;
  62. }*/
  63. private static BaseObject GetParent(ISubObject link)
  64. {
  65. while (true)
  66. {
  67. var parent = link.GetLinkedParent();
  68. if(parent is IEntityLink parentLink)
  69. {
  70. link = parentLink;
  71. }
  72. else
  73. {
  74. return parent;
  75. }
  76. }
  77. }
  78. private static string GetPath(ISubObject link)
  79. {
  80. var path = link.GetLinkedPath();
  81. while (true)
  82. {
  83. var parent = link.GetLinkedParent();
  84. if (parent is IEntityLink parentLink)
  85. {
  86. link = parentLink;
  87. path = $"{link.GetLinkedPath()}.{path}";
  88. }
  89. else
  90. {
  91. return path;
  92. }
  93. }
  94. }
  95. public static IEnumerable<ILinkedProperty> FindAll(Type parent)
  96. {
  97. if (_LinkedProperties.TryGetValue(parent, out var props))
  98. {
  99. return props;
  100. }
  101. return Enumerable.Empty<ILinkedProperty>();
  102. }
  103. public static IEnumerable<ILinkedProperty> Find(ISubObject subObject, out BaseObject parent)
  104. {
  105. parent = GetParent(subObject);
  106. if (!_LinkedProperties.TryGetValue(parent.GetType(), out var props))
  107. {
  108. return Enumerable.Empty<ILinkedProperty>();
  109. }
  110. var path = GetPath(subObject);
  111. return props.Where(x => x.Path == path);
  112. }
  113. public static bool Find(ISubObject subObject, string name, [NotNullWhen(true)] out ILinkedProperty? property, out BaseObject parent)
  114. {
  115. property = null;
  116. parent = GetParent(subObject);
  117. if (parent == null)
  118. return false;
  119. if(!_LinkedProperties.TryGetValue(parent.GetType(), out var props))
  120. return false;
  121. var path = GetPath(subObject);
  122. property = props.FirstOrDefault(x => String.Equals($"{x.Path}{(String.IsNullOrWhiteSpace(x.Path) ? "" : ".")}{x.Source}", $"{path}{(String.IsNullOrWhiteSpace(path) ? "" : ".")}{name}"));
  123. return property != null;
  124. }
  125. }
  126. }