/// <summary> /// Method to convert the identifier from string to <see cref="Expression"/>. /// </summary> /// <param name="context">The context of evaluation</param> /// <param name="message">The message to convert</param> /// <param name="data">Result expression data</param> /// <returns>The result expression</returns> public override Expression GetExpression(EvaluationContext context, string message, ref ExpressionData data) { string valObj = message.ToLowerInvariant(); if (valObj == "true") { return(Expression.Constant(true, typeof(bool))); } if (valObj == "false") { return(Expression.Constant(false, typeof(bool))); } string[] me = message.Split(new[] { '.' }, 2); // parameter first Expression exp = context.ParamListExpressions.FirstOrDefault(p => p.Name == me[0]); Type t = null; string rest = null; // found the parameter if (exp != null) { rest = me.Length > 1 ? me[1] : null; if (string.IsNullOrEmpty(rest)) { return(exp); } } // check the defined type aliases if (exp == null && context.TypeAliases.ContainsKey(me[0])) { t = context.TypeAliases[me[0]]; rest = me.Length > 1 ? me[1] : null; //MemberInfo[] mi = t.GetMember(me[1]); //return Expression.MakeMemberAccess(null, me[0]); } if (exp == null && t == null) { Assembly[] asm = Reflect.GetAssemblies(); // find class in included namespaces me = message.Split(new[] { '.' }); foreach (var ns in new[] { string.Empty }.Union(context.Namespaces)) { // search nested namespaces for (int i = 0; i < me.Length && t == null; i++) { Type t0 = asm.Select(o => o.GetType($"{ns}.{string.Join(".", me.Take(i + 1).ToArray())}", false)) .FirstOrDefault(o => o != null); if (t0 != null) { t = t0; rest = string.Join(".", me.Skip(i + 1).ToArray()); } } if (t != null) { break; } } } if (exp == null && t == null) { throw new EvaluationException($"Unable to evaluate {message}"); } if (string.IsNullOrEmpty(rest)) { CastTo(t, ref data); return(null); } else { me = rest.Split(new[] { '.' }); Type t2; foreach (string m in me) { t = t ?? exp?.Type; if (exp == null || t == null) { MemberInfo[] mi = t.GetMember(m); if (me.Length > 0) { exp = Expression.MakeMemberAccess(exp, mi[0]); t = t2 = exp.Type; continue; } } #if NETSTANDARD t2 = t.GetTypeInfo().GetProperty(m)?.PropertyType; #else t2 = t.GetProperty(m)?.PropertyType; #endif if (t == null) { throw new EvaluationException($"Unable to find property {m} on type {t.Name}."); } #if NETSTANDARD if (exp.Type.GetTypeInfo().IsAssignableFrom((Type)null)) #else if (exp.Type.IsAssignableFrom((Type)null)) #endif { // checked exp = Expression.Coalesce( Expression.PropertyOrField(exp, m), Expression.Constant(null, exp.Type)); } else { // unchecked exp = Expression.PropertyOrField( exp, m); } } } if (exp != null) { return(exp); } if (t == null) { throw new EvaluationException($"Unable to evaluate {rest} on type {t.FullName}"); } return(null); }