private static ExpressionNode ParseAgainstModel(Type modelType, string expression, ExpressionScope expressionScope, IMemberLocator memberLocator, SourceLocation location) { var dotIndex = expression.IndexOf('.'); if (dotIndex >= 0) { var subModel = ParseAgainstModel(modelType, expression.Substring(0, dotIndex), expressionScope, memberLocator, location.SetLength(dotIndex)); return SyntaxTreeExpression.SubModel( subModel, ParseAgainstModel(subModel.ResultType, expression.Substring(dotIndex + 1), ExpressionScope.CurrentModelOnStack, memberLocator, location.MoveIndex(dotIndex + 1)), location ); } if (expression.EndsWith("()")) { var func = memberLocator.FindMethod(modelType, expression.Substring(0, expression.Length - 2)); if (func != null) return SyntaxTreeExpression.Function(modelType, func.Name, location, expressionScope); } var prop = memberLocator.FindProperty(modelType, expression); if (prop != null) return SyntaxTreeExpression.Property(modelType, prop.Name, location, expressionScope); var field = memberLocator.FindField(modelType, expression); if (field != null) return SyntaxTreeExpression.Field(modelType, field.Name, location, expressionScope); if (IsLateBoundAcceptingType(modelType)) return SyntaxTreeExpression.LateBound(expression, location, memberLocator, false, expressionScope); throw new VeilParserException( $"Unable to parse model expression '{expression}' againt model '{modelType.Name}'", location); }
public static Func<object, object> GetBinder(object model, string itemName, IMemberLocator memberLocator) { var binder = LateBoundCache.GetOrAdd(Tuple.Create(model.GetType(), itemName), pair => { var type = pair.Item1; var name = pair.Item2; if (name.EndsWith("()")) { var function = memberLocator.FindMethod(type, name.Substring(0, name.Length - 2)); if (function != null) return DelegateBuilder.FunctionCall(type, function); } var property = memberLocator.FindProperty(type, name); if (property != null) return DelegateBuilder.Property(type, property); var field = memberLocator.FindField(type, name); if (field != null) return DelegateBuilder.Field(type, field); var dictionaryType = type.GetDictionaryTypeWithKey(); if (dictionaryType != null) return DelegateBuilder.Dictionary(dictionaryType, name); return null; }); return binder; }