Explorar o código

Added null-propagation for Expression.Getter (for future improvement of serialization)

Kenric Nugteren hai 7 meses
pai
achega
1578858a22
Modificáronse 3 ficheiros con 54 adicións e 38 borrados
  1. 1 7
      InABox.Core/BaseObject.cs
  2. 53 30
      InABox.Core/Expressions.cs
  3. 0 1
      InABox.Core/Licensing/LicenseUtils.cs

+ 1 - 7
InABox.Core/BaseObject.cs

@@ -324,13 +324,7 @@ namespace InABox.Core
             if (!IsObserving())
                 return;
 
-            if (name.Equals("IsChanged"))
-                return;
-
-            if (name.Equals("Observing"))
-                return;
-
-            if (name.Equals("OriginalValues"))
+            if (name.Equals("IsChanged") || name.Equals("Observing") || name.Equals("OriginalValues"))
                 return;
 
             LoadedColumns.Add(name);

+ 53 - 30
InABox.Core/Expressions.cs

@@ -1,4 +1,7 @@
-using System;
+using InABox.Clients;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
 using System.Linq;
 using System.Linq.Expressions;
 using System.Reflection;
@@ -11,51 +14,71 @@ namespace InABox.Core
 
         // Allows setting of object properties via cached expressions
 
-        public static Func<T, TValue> Getter<T, TValue>(Expression<Func<T, TValue>> expression)
+        public static Expression NullPropagatingPropertyOrField(Expression expression, string propName)
         {
-            return expression.Compile();
+            var param = Expression.Parameter(expression.Type);
+            var access = Expression.PropertyOrField(param, propName);
+            return Expression.Block(new[] { param },
+                Expression.Assign(param, expression),
+                Expression.Condition(Expression.Equal(param, Expression.Constant(null)),
+                    Expression.Default(access.Type),
+                    access));
         }
 
-        public static Func<T, object> Getter<T>(string propname)
+        private static Func<T, TProp>? MakeGetter<T, TProp>(Type objectType, string propname, bool propagateNulls = false)
         {
-            Func<T, object>? result = null;
             try
             {
-                var param = Expression.Parameter(typeof(T), "x");
-                Expression body = param;
-                foreach (var member in propname.Split('.'))
-                    body = Expression.PropertyOrField(body, member);
-                var lambda = Expression.Lambda<Func<T, object>>(body, param);
-                result = lambda.Compile();
+                var objectParameter = Expression.Parameter(typeof(T), "o");
+                Expression param;
+                if(typeof(T) != objectType)
+                {
+                    param = Expression.ConvertChecked(objectParameter, objectType);
+                }
+                else
+                {
+                    param = objectParameter;
+                }
+
+                var body = param;
+                if(propname != "")
+                {
+                    foreach (var member in propname.Split('.'))
+                        body = propagateNulls
+                            ? NullPropagatingPropertyOrField(body, member)
+                            : Expression.PropertyOrField(body, member);
+                }
+
+                if(typeof(TProp) != body.Type)
+                {
+                    body = Expression.Convert(body, typeof(TProp));
+                }
+
+                var lambda = Expression.Lambda<Func<T, TProp>>(body, objectParameter);
+                return lambda.Compile();
             }
             catch (Exception e)
             {
                 Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
+                return null;
             }
+        }
 
-            return result;
+        public static Func<T, TValue> Getter<T, TValue>(Expression<Func<T, TValue>> expression, bool propagateNulls = false)
+        {
+            return propagateNulls
+                ?  MakeGetter<T, TValue>(typeof(T), CoreUtils.GetFullPropertyName(expression, "."), propagateNulls: true)
+                : expression.Compile();
         }
 
-        public static Func<object, object> Getter(Type objectType, string propname)
+        public static Func<T, object> Getter<T>(string propname, bool propagateNulls = false)
         {
-            Func<object, object> result = null;
-            try
-            {
-                var objectParameter = Expression.Parameter(typeof(object), "o");
-                var param = Expression.ConvertChecked(objectParameter, objectType);
-                Expression body = param;
-                foreach (var member in propname.Split('.'))
-                    body = Expression.PropertyOrField(body, member);
-                Expression conversion = Expression.Convert(body, typeof(object));
-                var lambda = Expression.Lambda<Func<object, object>>(conversion, objectParameter);
-                result = lambda.Compile();
-            }
-            catch (Exception e)
-            {
-                Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
-            }
+            return MakeGetter<T, object>(typeof(T), propname, propagateNulls: propagateNulls);
+        }
 
-            return result;
+        public static Func<object, object> Getter(Type objectType, string propname, bool propagateNulls = false)
+        {
+            return MakeGetter<object, object>(objectType, propname, propagateNulls: propagateNulls);
         }
 
         public static Func<T, object> Getter<T>(string propname, string key)

+ 0 - 1
InABox.Core/Licensing/LicenseUtils.cs

@@ -32,7 +32,6 @@ namespace InABox.Core
         
         #region License Generation
         
-
         public static LicenseData RenewLicense(LicenseData oldLicense, DateTime renewed, DateTime newExpiry, DateTime renewAvailable, String[] addresses)
         {
             return new LicenseData