瀏覽代碼

Implementing lazy entitylinks

Kenric Nugteren 8 月之前
父節點
當前提交
6b9c5b7bd8

+ 71 - 41
InABox.Core/BaseObject.cs

@@ -1,4 +1,5 @@
-using Newtonsoft.Json;
+using AutoProperties;
+using Newtonsoft.Json;
 using System;
 using System.Collections;
 using System.Collections.Concurrent;
@@ -127,13 +128,38 @@ namespace InABox.Core
         public BaseObject()
         {
             SetObserving(false);
-
-            DatabaseSchema.InitializeSubObjects(this);
-
             Init();
             SetObserving(true);
         }
 
+        private bool _disabledInterceptor;
+
+        [GetInterceptor]
+        protected T GetValue<T>(Type propertyType, ref T field, string name)
+        {
+            if (_disabledInterceptor) return field;
+
+            if(field is null && propertyType.HasInterface<ISubObject>() && !propertyType.IsAbstract)
+            {
+                var value = Activator.CreateInstance<T>();
+                var subObj = (value as ISubObject)!;
+                subObj.SetLinkedParent(this);
+                subObj.SetLinkedPath(name);
+                if(subObj is BaseObject obj)
+                {
+                    obj.SetObserving(_observing);
+                }
+                field = value;
+            }
+            return field;
+        }
+
+        [SetInterceptor]
+        protected void SetValue<T>(ref T field, T newValue)
+        {
+            field = newValue;
+        }
+
         [OnDeserializing]
         internal void OnDeserializingMethod(StreamingContext context)
         {
@@ -151,15 +177,6 @@ namespace InABox.Core
         protected virtual void Init()
         {
             LoadedColumns = CreateLoadedColumns();
-
-            UserProperties = new UserProperties();
-            //UserProperties.ParentType = this.GetType();
-            DatabaseSchema.InitializeObject(this);
-            UserProperties.OnPropertyChanged += (o, n, b, a) =>
-            {
-                if (IsObserving())
-                    OnPropertyChanged(n, b, a);
-            };
             
             CheckSequence();
         }
@@ -187,8 +204,10 @@ namespace InABox.Core
         {
             bApplyingChanges = true;
             _observing = active;
+            _disabledInterceptor = true;
             foreach (var oo in DatabaseSchema.GetSubObjects(this))
                 oo.SetObserving(active);
+            _disabledInterceptor = false;
             bApplyingChanges = false;
         }
 
@@ -201,7 +220,7 @@ namespace InABox.Core
 
         private bool bChanged;
 
-        private IOriginalValues _originalValues;
+        private IOriginalValues? _originalValues;
         [DoNotPersist]
         [DoNotSerialize]
         public IOriginalValues OriginalValueList
@@ -239,6 +258,7 @@ namespace InABox.Core
         [DoNotPersist]
         [DoNotSerialize]
         [JsonIgnore]
+        [InterceptIgnore]
         public ILoadedColumns LoadedColumns { get; set; }
 
         protected virtual void SetChanged(string name, object? before, object? after)
@@ -256,7 +276,7 @@ namespace InABox.Core
 
                     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
                 }
-                catch (Exception e)
+                catch (Exception)
                 {
                     
                 }
@@ -275,9 +295,14 @@ namespace InABox.Core
             if (OriginalValueList.Any())
                 return true;
 
+            _disabledInterceptor = true;
             foreach (var oo in DatabaseSchema.GetSubObjects(this))
                 if (oo.IsChanged())
+                {
+                    _disabledInterceptor = false;
                     return true;
+                }
+            _disabledInterceptor = false;
 
             return false;
         }
@@ -351,8 +376,12 @@ namespace InABox.Core
 
             bChanged = false;
 
-
-            foreach (var oo in DatabaseSchema.GetSubObjects(this)) oo.CancelChanges();
+            _disabledInterceptor = true;
+            foreach (var oo in DatabaseSchema.GetSubObjects(this))
+            {
+                oo.CancelChanges();
+            }
+            _disabledInterceptor = false;
 
             SetObserving(bObs);
             bApplyingChanges = false;
@@ -366,8 +395,10 @@ namespace InABox.Core
 
             bChanged = false;
 
+            _disabledInterceptor = true;
             foreach (var oo in DatabaseSchema.GetSubObjects(this))
                 oo.CommitChanges();
+            _disabledInterceptor = false;
 
             bApplyingChanges = false;
         }
@@ -422,39 +453,38 @@ namespace InABox.Core
 
         #region UserProperties
 
-        private UserProperties _userproperties;
+        private UserProperties? _userproperties;
+
+        private static readonly Dictionary<Type, Dictionary<string, object?>> DefaultProperties = new Dictionary<Type, Dictionary<string, object?>>();
 
         [DoNotPersist]
         public UserProperties UserProperties
         {
             get
             {
-                CheckUserProperties();
-                return _userproperties;
-            }
-            set
-            {
-                _userproperties = value;
-                CheckUserProperties();
-            }
-        }
+                if (_userproperties == null)
+                {
+                    _userproperties = new UserProperties();
 
-        private static Dictionary<string, object?>? DefaultProperties;
+                    var type = GetType();
+                    if (!DefaultProperties.TryGetValue(type, out var defaultProps))
+                    {
+                        defaultProps = new Dictionary<string, object?>();
+                        var props = DatabaseSchema.Properties(type).Where(x => x is CustomProperty);
+                        foreach (var field in props)
+                            defaultProps[field.Name] = DatabaseSchema.DefaultValue(field.PropertyType);
+                        DefaultProperties[type] = defaultProps;
+                    }
 
-        private void CheckUserProperties()
-        {
-            if (_userproperties == null)
-            {
-                _userproperties = new UserProperties();
-                if (DefaultProperties == null)
-                {
-                    DefaultProperties = new Dictionary<string, object?>();
-                    var props = DatabaseSchema.Properties(GetType()).Where(x => x is CustomProperty).ToArray();
-                    foreach (var field in props)
-                        DefaultProperties[field.Name] = DatabaseSchema.DefaultValue(field.PropertyType);
-                }
+                    _userproperties.LoadFromDictionary(defaultProps);
 
-                _userproperties.LoadFromDictionary(DefaultProperties);
+                    _userproperties.OnPropertyChanged += (o, n, b, a) =>
+                    {
+                        if (IsObserving())
+                            OnPropertyChanged(n, b, a);
+                    };
+                }
+                return _userproperties;
             }
         }
 

+ 0 - 7
InABox.Core/DatabaseSchema/DatabaseSchema.cs

@@ -366,12 +366,5 @@ namespace InABox.Core
         }
         public static IProperty? Property<T>(Expression<Func<T, object?>> expression) => Property(typeof(T), CoreUtils.GetFullPropertyName(expression, "."));
         public static IProperty? Property<T, TType>(Expression<Func<T, TType>> expression) => Property(typeof(T), CoreUtils.GetFullPropertyName(expression, "."));
-
-        public static void InitializeObject<TObject>(TObject entity) where TObject : BaseObject
-        {
-            entity.UserProperties.Load(Properties(entity.GetType())
-                .Where(x => x is CustomProperty)
-                .Select(x => new KeyValuePair<string, object?>(x.Name, DefaultValue(x.PropertyType))));
-        }
     }
 }

+ 1 - 0
InABox.Core/FodyWeavers.xml

@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
+	<AutoProperties/>
     <PropertyChanged/>
 </Weavers>

+ 1 - 0
InABox.Core/FodyWeavers.xsd

@@ -53,6 +53,7 @@
             </xs:attribute>
           </xs:complexType>
         </xs:element>
+        <xs:element name="AutoProperties" minOccurs="0" maxOccurs="1" type="xs:anyType" />
       </xs:all>
       <xs:attribute name="VerifyAssembly" type="xs:boolean">
         <xs:annotation>

+ 1 - 0
InABox.Core/InABox.Core.csproj

@@ -23,6 +23,7 @@
         <None Remove=".gitignore" />
     </ItemGroup>
     <ItemGroup>
+        <PackageReference Include="AutoProperties.Fody" Version="1.25.0" />
         <PackageReference Include="ExpressiveParser" Version="3.0.1" />
         <PackageReference Include="FluentResults" Version="3.15.2" />
         <PackageReference Include="Fody" Version="6.8.1">