| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 | 
							- using System;
 
- using System.Linq;
 
- using System.Linq.Expressions;
 
- using System.Reflection;
 
- namespace InABox.Core
 
- {
 
-     public static class Expressions
 
-     {
 
-         #region Property Getter Setter Functions
 
-         // Allows setting of object properties via cached expressions
 
-         public static Func<T, object> Getter<T>(string propname)
 
-         {
 
-             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();
 
-             }
 
-             catch (Exception e)
 
-             {
 
-                 Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
 
-             }
 
-             return result;
 
-         }
 
-         public static Func<object, object> Getter(Type objectType, string propname)
 
-         {
 
-             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 result;
 
-         }
 
-         public static Func<T, object> Getter<T>(string propname, string key)
 
-         {
 
-             Func<T, object> result = null;
 
-             try
 
-             {
 
-                 var param = Expression.Parameter(typeof(T), "o");
 
-                 Expression body = param;
 
-                 foreach (var member in propname.Split('.'))
 
-                     body = Expression.PropertyOrField(body, member);
 
-                 Expression keyExpr = Expression.Constant(key, typeof(string)); //Parameter(typeof(string));
 
-                 // Alternative, note that we could even look for the type of parameters, if there are indexer overloads.
 
-                 var indexer = (from p in body.Type.GetDefaultMembers().OfType<PropertyInfo>()
 
-                     // This check is probably useless. You can't overload on return value in C#.
 
-                     where p.PropertyType == typeof(object)
 
-                     let q = p.GetIndexParameters()
 
-                     // Here we can search for the exact overload. Length is the number of "parameters" of the indexer, and then we can check for their type.
 
-                     where q.Length == 1 && q[0].ParameterType == typeof(string)
 
-                     select p).Single();
 
-                 var indexExpr = Expression.Property(body, indexer, keyExpr);
 
-                 var lambdaGetter = Expression.Lambda<Func<T, object>>(indexExpr, param);
 
-                 result = lambdaGetter.Compile();
 
-             }
 
-             catch (Exception e)
 
-             {
 
-                 Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
 
-             }
 
-             return result;
 
-         }
 
-         public static Func<object, object> Getter(Type objectType, string propname, string key)
 
-         {
 
-             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 keyExpr = Expression.Constant(key, typeof(string)); //Parameter(typeof(string));
 
-                 // Alternative, note that we could even look for the type of parameters, if there are indexer overloads.
 
-                 var indexer = (from p in body.Type.GetDefaultMembers().OfType<PropertyInfo>()
 
-                     // This check is probably useless. You can't overload on return value in C#.
 
-                     where p.PropertyType == typeof(object)
 
-                     let q = p.GetIndexParameters()
 
-                     // Here we can search for the exact overload. Length is the number of "parameters" of the indexer, and then we can check for their type.
 
-                     where q.Length == 1 && q[0].ParameterType == typeof(string)
 
-                     select p).Single();
 
-                 var indexExpr = Expression.Property(body, indexer, keyExpr);
 
-                 var lambdaGetter = Expression.Lambda<Func<object, object>>(indexExpr, objectParameter);
 
-                 result = lambdaGetter.Compile();
 
-             }
 
-             catch (Exception e)
 
-             {
 
-                 Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
 
-             }
 
-             return result;
 
-         }
 
-         public static bool IsWriteable(Expression expression)
 
-         {
 
-             switch (expression.NodeType)
 
-             {
 
-                 case ExpressionType.Index:
 
-                     return expression is IndexExpression index && index.Indexer is PropertyInfo indexer && indexer.CanWrite;
 
-                 case ExpressionType.MemberAccess:
 
-                     if(expression is MemberExpression me)
 
-                     {
 
-                         if (me.Member is PropertyInfo prop)
 
-                             return prop.CanWrite;
 
-                         else if (me.Member is FieldInfo field)
 
-                             return !(field.IsInitOnly || field.IsLiteral);
 
-                     }
 
-                     return false;
 
-                 case ExpressionType.Parameter:
 
-                     return true;
 
-             }
 
-             return false;
 
-         }
 
-         public static Action<T, object> Setter<T>(string propname)
 
-         {
 
-             var param = Expression.Parameter(typeof(T), "o");
 
-             Expression body = param;
 
-             foreach (var member in propname.Split('.'))
 
-                 body = Expression.PropertyOrField(body, member);
 
-             var valueParameter = Expression.Parameter(typeof(object), "v");
 
-             var value = Expression.ConvertChecked(valueParameter, body.Type);
 
-             Expression expression;
 
-             if (IsWriteable(body))
 
-             {
 
-                 try
 
-                 {
 
-                     expression = Expression.Assign(body, value);
 
-                 }
 
-                 catch
 
-                 {
 
-                     expression = Expression.Empty();
 
-                 }
 
-             }
 
-             else
 
-             {
 
-                 expression = Expression.Empty();
 
-             }
 
-             var lambda = Expression.Lambda<Action<T, object>>(expression, param, valueParameter);
 
-             var compiled = lambda.Compile();
 
-             return compiled;
 
-         }
 
-         public static Action<object, object> Setter(Type objectType, string propname, Type type = null)
 
-         {
 
-             Action<object, object> compiled = 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);
 
-                 var valueParameter = Expression.Parameter(typeof(object), "v");
 
-                 UnaryExpression value = null;
 
-                 if (type != null)
 
-                 {
 
-                     var val1 = Expression.Convert(valueParameter, type);
 
-                     value = Expression.ConvertChecked(val1, body.Type);
 
-                 }
 
-                 else
 
-                 {
 
-                     value = Expression.ConvertChecked(valueParameter, body.Type);
 
-                 }
 
-                 Expression expression;
 
-                 if (IsWriteable(body))
 
-                 {
 
-                     try
 
-                     {
 
-                         expression = Expression.Assign(body, value);
 
-                     }
 
-                     catch
 
-                     {
 
-                         expression = Expression.Empty();
 
-                     }
 
-                 }
 
-                 else
 
-                 {
 
-                     expression = Expression.Empty();
 
-                 }
 
-                 var lambda = Expression.Lambda<Action<object, object>>(expression, objectParameter, valueParameter);
 
-                 compiled = lambda.Compile();
 
-             }
 
-             catch (Exception e)
 
-             {
 
-                 Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
 
-             }
 
-             return compiled;
 
-         }
 
-         public static Action<T, object> Setter<T>(string propname, string key)
 
-         {
 
-             Action<T, object> result = null;
 
-             try
 
-             {
 
-                 var param = Expression.Parameter(typeof(T), "o");
 
-                 Expression body = param;
 
-                 foreach (var member in propname.Split('.'))
 
-                     body = Expression.PropertyOrField(body, member);
 
-                 Expression keyExpr = Expression.Constant(key, typeof(string));
 
-                 var valueExpr = Expression.Parameter(typeof(object));
 
-                 // Alternative, note that we could even look for the type of parameters, if there are indexer overloads.
 
-                 var indexer = (from p in body.Type.GetDefaultMembers().OfType<PropertyInfo>()
 
-                     // This check is probably useless. You can't overload on return value in C#.
 
-                     where p.PropertyType == typeof(object)
 
-                     let q = p.GetIndexParameters()
 
-                     // Here we can search for the exact overload. Length is the number of "parameters" of the indexer, and then we can check for their type.
 
-                     where q.Length == 1 && q[0].ParameterType == typeof(string)
 
-                     select p).Single();
 
-                 var indexExpr = Expression.Property(body, indexer, keyExpr);
 
-                 var assign = Expression.Assign(indexExpr, valueExpr);
 
-                 var lambdaSetter = Expression.Lambda<Action<T, object>>(assign, param, valueExpr);
 
-                 result = lambdaSetter.Compile();
 
-             }
 
-             catch (Exception e)
 
-             {
 
-                 Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
 
-             }
 
-             return result;
 
-         }
 
-         public static Action<object, object> Setter(Type objectType, string propname, string key)
 
-         {
 
-             Action<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 keyExpr = Expression.Constant(key, typeof(string));
 
-                 var valueExpr = Expression.Parameter(typeof(object));
 
-                 // Alternative, note that we could even look for the type of parameters, if there are indexer overloads.
 
-                 var indexer = (from p in body.Type.GetDefaultMembers().OfType<PropertyInfo>()
 
-                     // This check is probably useless. You can't overload on return value in C#.
 
-                     where p.PropertyType == typeof(object)
 
-                     let q = p.GetIndexParameters()
 
-                     // Here we can search for the exact overload. Length is the number of "parameters" of the indexer, and then we can check for their type.
 
-                     where q.Length == 1 && q[0].ParameterType == typeof(string)
 
-                     select p).Single();
 
-                 var indexExpr = Expression.Property(body, indexer, keyExpr);
 
-                 var assign = Expression.Assign(indexExpr, valueExpr);
 
-                 var lambdaSetter = Expression.Lambda<Action<object, object>>(assign, objectParameter, valueExpr);
 
-                 result = lambdaSetter.Compile();
 
-             }
 
-             catch (Exception e)
 
-             {
 
-                 Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
 
-             }
 
-             return result;
 
-         }
 
-         #endregion
 
-     }
 
- }
 
 
  |