diff --git a/src/Umbraco.Core/Dynamics/ClassFactory.cs b/src/Umbraco.Core/Dynamics/ClassFactory.cs index 8edd9839d5..87f4315e76 100644 --- a/src/Umbraco.Core/Dynamics/ClassFactory.cs +++ b/src/Umbraco.Core/Dynamics/ClassFactory.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Dynamics int classCount; ReaderWriterLock rwLock; - private ClassFactory() + protected ClassFactory() { AssemblyName name = new AssemblyName("DynamicClasses"); AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run); diff --git a/src/Umbraco.Core/Dynamics/ExpressionParser.cs b/src/Umbraco.Core/Dynamics/ExpressionParser.cs index cbfeef27a9..a3cbb5803a 100644 --- a/src/Umbraco.Core/Dynamics/ExpressionParser.cs +++ b/src/Umbraco.Core/Dynamics/ExpressionParser.cs @@ -1006,7 +1006,7 @@ namespace Umbraco.Core.Dynamics } } - static object ReflectPropertyValue(object o, string name) + public static object ReflectPropertyValue(object o, string name) { PropertyInfo propertyInfo = o.GetType().GetProperty(name); if (propertyInfo != null) diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/ClassFactory.cs b/src/umbraco.MacroEngines/RazorDynamicNode/ClassFactory.cs index d43d0babdb..e089899a6a 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/ClassFactory.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/ClassFactory.cs @@ -5,177 +5,9 @@ using System.Threading; namespace System.Linq.Dynamic { - internal class ClassFactory + [Obsolete("This class has been superceded by Umbraco.Core.Dynamics.ClassFactory")] + internal class ClassFactory : Umbraco.Core.Dynamics.ClassFactory { - public static readonly ClassFactory Instance = new ClassFactory(); - - static ClassFactory() { } // Trigger lazy initialization of static fields - - ModuleBuilder module; - Dictionary classes; - int classCount; - ReaderWriterLock rwLock; - - private ClassFactory() - { - AssemblyName name = new AssemblyName("DynamicClasses"); - AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run); -#if ENABLE_LINQ_PARTIAL_TRUST - new ReflectionPermission(PermissionState.Unrestricted).Assert(); -#endif - try - { - module = assembly.DefineDynamicModule("Module"); - } - finally - { -#if ENABLE_LINQ_PARTIAL_TRUST - PermissionSet.RevertAssert(); -#endif - } - classes = new Dictionary(); - rwLock = new ReaderWriterLock(); - } - - public Type GetDynamicClass(IEnumerable properties) - { - rwLock.AcquireReaderLock(Timeout.Infinite); - try - { - Signature signature = new Signature(properties); - Type type; - if (!classes.TryGetValue(signature, out type)) - { - type = CreateDynamicClass(signature.properties); - classes.Add(signature, type); - } - return type; - } - finally - { - rwLock.ReleaseReaderLock(); - } - } - - Type CreateDynamicClass(DynamicProperty[] properties) - { - LockCookie cookie = rwLock.UpgradeToWriterLock(Timeout.Infinite); - try - { - string typeName = "DynamicClass" + (classCount + 1); -#if ENABLE_LINQ_PARTIAL_TRUST - new ReflectionPermission(PermissionState.Unrestricted).Assert(); -#endif - try - { - TypeBuilder tb = this.module.DefineType(typeName, TypeAttributes.Class | - TypeAttributes.Public, typeof(DynamicClass)); - FieldInfo[] fields = GenerateProperties(tb, properties); - GenerateEquals(tb, fields); - GenerateGetHashCode(tb, fields); - Type result = tb.CreateType(); - classCount++; - return result; - } - finally - { -#if ENABLE_LINQ_PARTIAL_TRUST - PermissionSet.RevertAssert(); -#endif - } - } - finally - { - rwLock.DowngradeFromWriterLock(ref cookie); - } - } - - FieldInfo[] GenerateProperties(TypeBuilder tb, DynamicProperty[] properties) - { - FieldInfo[] fields = new FieldBuilder[properties.Length]; - for (int i = 0; i < properties.Length; i++) - { - DynamicProperty dp = properties[i]; - FieldBuilder fb = tb.DefineField("_" + dp.Name, dp.Type, FieldAttributes.Private); - PropertyBuilder pb = tb.DefineProperty(dp.Name, PropertyAttributes.HasDefault, dp.Type, null); - MethodBuilder mbGet = tb.DefineMethod("get_" + dp.Name, - MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, - dp.Type, Type.EmptyTypes); - ILGenerator genGet = mbGet.GetILGenerator(); - genGet.Emit(OpCodes.Ldarg_0); - genGet.Emit(OpCodes.Ldfld, fb); - genGet.Emit(OpCodes.Ret); - MethodBuilder mbSet = tb.DefineMethod("set_" + dp.Name, - MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, - null, new Type[] { dp.Type }); - ILGenerator genSet = mbSet.GetILGenerator(); - genSet.Emit(OpCodes.Ldarg_0); - genSet.Emit(OpCodes.Ldarg_1); - genSet.Emit(OpCodes.Stfld, fb); - genSet.Emit(OpCodes.Ret); - pb.SetGetMethod(mbGet); - pb.SetSetMethod(mbSet); - fields[i] = fb; - } - return fields; - } - - void GenerateEquals(TypeBuilder tb, FieldInfo[] fields) - { - MethodBuilder mb = tb.DefineMethod("Equals", - MethodAttributes.Public | MethodAttributes.ReuseSlot | - MethodAttributes.Virtual | MethodAttributes.HideBySig, - typeof(bool), new Type[] { typeof(object) }); - ILGenerator gen = mb.GetILGenerator(); - LocalBuilder other = gen.DeclareLocal(tb); - Label next = gen.DefineLabel(); - gen.Emit(OpCodes.Ldarg_1); - gen.Emit(OpCodes.Isinst, tb); - gen.Emit(OpCodes.Stloc, other); - gen.Emit(OpCodes.Ldloc, other); - gen.Emit(OpCodes.Brtrue_S, next); - gen.Emit(OpCodes.Ldc_I4_0); - gen.Emit(OpCodes.Ret); - gen.MarkLabel(next); - foreach (FieldInfo field in fields) - { - Type ft = field.FieldType; - Type ct = typeof(EqualityComparer<>).MakeGenericType(ft); - next = gen.DefineLabel(); - gen.EmitCall(OpCodes.Call, ct.GetMethod("get_Default"), null); - gen.Emit(OpCodes.Ldarg_0); - gen.Emit(OpCodes.Ldfld, field); - gen.Emit(OpCodes.Ldloc, other); - gen.Emit(OpCodes.Ldfld, field); - gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("Equals", new Type[] { ft, ft }), null); - gen.Emit(OpCodes.Brtrue_S, next); - gen.Emit(OpCodes.Ldc_I4_0); - gen.Emit(OpCodes.Ret); - gen.MarkLabel(next); - } - gen.Emit(OpCodes.Ldc_I4_1); - gen.Emit(OpCodes.Ret); - } - - void GenerateGetHashCode(TypeBuilder tb, FieldInfo[] fields) - { - MethodBuilder mb = tb.DefineMethod("GetHashCode", - MethodAttributes.Public | MethodAttributes.ReuseSlot | - MethodAttributes.Virtual | MethodAttributes.HideBySig, - typeof(int), Type.EmptyTypes); - ILGenerator gen = mb.GetILGenerator(); - gen.Emit(OpCodes.Ldc_I4_0); - foreach (FieldInfo field in fields) - { - Type ft = field.FieldType; - Type ct = typeof(EqualityComparer<>).MakeGenericType(ft); - gen.EmitCall(OpCodes.Call, ct.GetMethod("get_Default"), null); - gen.Emit(OpCodes.Ldarg_0); - gen.Emit(OpCodes.Ldfld, field); - gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("GetHashCode", new Type[] { ft }), null); - gen.Emit(OpCodes.Xor); - } - gen.Emit(OpCodes.Ret); - } + } } \ No newline at end of file diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicClass.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicClass.cs index 80c08c56ee..1fc76493ea 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicClass.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicClass.cs @@ -3,22 +3,10 @@ using System.Text; namespace System.Linq.Dynamic { - public abstract class DynamicClass + + [Obsolete("This class has been superceded by Umbraco.Core.Dynamics.DynamicClass")] + public abstract class DynamicClass : Umbraco.Core.Dynamics.DynamicClass { - public override string ToString() - { - PropertyInfo[] props = this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); - StringBuilder sb = new StringBuilder(); - sb.Append("{"); - for (int i = 0; i < props.Length; i++) - { - if (i > 0) sb.Append(", "); - sb.Append(props[i].Name); - sb.Append("="); - sb.Append(props[i].GetValue(this, null)); - } - sb.Append("}"); - return sb.ToString(); - } + } } \ No newline at end of file diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicExpression.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicExpression.cs index 52ca8851e8..9720fe69dd 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicExpression.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicExpression.cs @@ -3,41 +3,43 @@ using System.Linq.Expressions; namespace System.Linq.Dynamic { + + [Obsolete("This class has been superceded by Umbraco.Core.Dynamics.DynamicExpression")] public static class DynamicExpression { - public static bool ConvertDynamicNullToBooleanFalse = false; + public static bool ConvertDynamicNullToBooleanFalse + { + get { return Umbraco.Core.Dynamics.DynamicExpression.ConvertDynamicNullToBooleanFalse; } + set { Umbraco.Core.Dynamics.DynamicExpression.ConvertDynamicNullToBooleanFalse = value; } + } public static Expression Parse(Type resultType, string expression, bool convertDynamicNullToBooleanFalse, params object[] values) { - ConvertDynamicNullToBooleanFalse = convertDynamicNullToBooleanFalse; - ExpressionParser parser = new ExpressionParser(null, expression, values); - return parser.Parse(resultType); + return Umbraco.Core.Dynamics.DynamicExpression.Parse(resultType, expression, convertDynamicNullToBooleanFalse, values); } public static LambdaExpression ParseLambda(Type itType, Type resultType, string expression, bool convertDynamicNullToBooleanFalse, params object[] values) { - return ParseLambda(new ParameterExpression[] { Expression.Parameter(itType, "") }, resultType, expression, convertDynamicNullToBooleanFalse, values); + return Umbraco.Core.Dynamics.DynamicExpression.ParseLambda(itType, resultType, expression, convertDynamicNullToBooleanFalse, values); } public static LambdaExpression ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, bool convertDynamicNullToBooleanFalse, params object[] values) { - ConvertDynamicNullToBooleanFalse = convertDynamicNullToBooleanFalse; - ExpressionParser parser = new ExpressionParser(parameters, expression, values); - return Expression.Lambda(parser.Parse(resultType), parameters); + return Umbraco.Core.Dynamics.DynamicExpression.ParseLambda(parameters, resultType, expression, convertDynamicNullToBooleanFalse, values); } public static Expression> ParseLambda(string expression, bool convertDynamicNullToBooleanFalse, params object[] values) { - return (Expression>)ParseLambda(typeof(T), typeof(S), expression, convertDynamicNullToBooleanFalse, values); + return Umbraco.Core.Dynamics.DynamicExpression.ParseLambda(expression, convertDynamicNullToBooleanFalse, values); } public static Type CreateClass(params DynamicProperty[] properties) { - return ClassFactory.Instance.GetDynamicClass(properties); + return Umbraco.Core.Dynamics.DynamicExpression.CreateClass(properties.Select(x => new Umbraco.Core.Dynamics.DynamicProperty(x.Name, x.Type))); } public static Type CreateClass(IEnumerable properties) { - return ClassFactory.Instance.GetDynamicClass(properties); + return Umbraco.Core.Dynamics.DynamicExpression.CreateClass(properties.Select(x => new Umbraco.Core.Dynamics.DynamicProperty(x.Name, x.Type))); } } } \ No newline at end of file diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicOrdering.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicOrdering.cs index 5b821083b3..fc6cb4da24 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicOrdering.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicOrdering.cs @@ -2,9 +2,9 @@ using System.Linq.Expressions; namespace System.Linq.Dynamic { - internal class DynamicOrdering + [Obsolete("This class has been superceded by Umbraco.Core.DynamicOrdering")] + internal class DynamicOrdering : Umbraco.Core.Dynamics.DynamicOrdering { - public Expression Selector; - public bool Ascending; + } } \ No newline at end of file diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicProperty.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicProperty.cs index 2f77710897..07425d97c2 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicProperty.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicProperty.cs @@ -1,26 +1,24 @@ namespace System.Linq.Dynamic { + + [Obsolete("This class has been superceded by Umbraco.Core.Dynamics.DynamicProperty")] public class DynamicProperty { - string name; - Type type; + private readonly Umbraco.Core.Dynamics.DynamicProperty _inner; public DynamicProperty(string name, Type type) { - if (name == null) throw new ArgumentNullException("name"); - if (type == null) throw new ArgumentNullException("type"); - this.name = name; - this.type = type; + _inner = new Umbraco.Core.Dynamics.DynamicProperty(name, type); } public string Name { - get { return name; } + get { return _inner.Name; } } public Type Type { - get { return type; } + get { return _inner.Type; } } } } \ No newline at end of file diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicQueryable.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicQueryable.cs index bf04f0221d..178ec05132 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicQueryable.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicQueryable.cs @@ -10,6 +10,8 @@ using System.Diagnostics; namespace System.Linq.Dynamic { + + public static class DynamicQueryable { public static IQueryable Where(this IQueryable source, string predicate, params object[] values) @@ -21,7 +23,7 @@ namespace System.Linq.Dynamic { if (source == null) throw new ArgumentNullException("source"); if (predicate == null) throw new ArgumentNullException("predicate"); - LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, true, values); + LambdaExpression lambda = Umbraco.Core.Dynamics.DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, true, values); if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(DynamicNode)) { //source list is DynamicNode and the lambda returns a Func @@ -91,7 +93,7 @@ namespace System.Linq.Dynamic { if (source == null) throw new ArgumentNullException("source"); if (selector == null) throw new ArgumentNullException("selector"); - LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(object), selector, false, values); + LambdaExpression lambda = Umbraco.Core.Dynamics.DynamicExpression.ParseLambda(source.ElementType, typeof(object), selector, false, values); if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(DynamicNode)) { //source list is DynamicNode and the lambda returns a Func @@ -149,7 +151,7 @@ namespace System.Linq.Dynamic descending = true; } - LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(object), ordering, false, values); + LambdaExpression lambda = Umbraco.Core.Dynamics.DynamicExpression.ParseLambda(source.ElementType, typeof(object), ordering, false, values); if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(DynamicNode)) { //source list is DynamicNode and the lambda returns a Func @@ -197,11 +199,11 @@ namespace System.Linq.Dynamic ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(source.ElementType, "") }; ExpressionParser parser = new ExpressionParser(parameters, ordering, values); - IEnumerable orderings = parser.ParseOrdering(); + var orderings = parser.ParseOrdering(); Expression queryExpr = source.Expression; string methodAsc = "OrderBy"; string methodDesc = "OrderByDescending"; - foreach (DynamicOrdering o in orderings) + foreach (var o in orderings) { if (!isDynamicNodeList) { @@ -286,8 +288,8 @@ namespace System.Linq.Dynamic if (source == null) throw new ArgumentNullException("source"); if (keySelector == null) throw new ArgumentNullException("keySelector"); if (elementSelector == null) throw new ArgumentNullException("elementSelector"); - LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, true, values); - LambdaExpression elementLambda = DynamicExpression.ParseLambda(source.ElementType, null, elementSelector, true, values); + LambdaExpression keyLambda = Umbraco.Core.Dynamics.DynamicExpression.ParseLambda(source.ElementType, null, keySelector, true, values); + LambdaExpression elementLambda = Umbraco.Core.Dynamics.DynamicExpression.ParseLambda(source.ElementType, null, elementSelector, true, values); return source.Provider.CreateQuery( Expression.Call( typeof(Queryable), "GroupBy", diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/ExpressionParser.cs b/src/umbraco.MacroEngines/RazorDynamicNode/ExpressionParser.cs index 6a42812336..b737b8eeff 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/ExpressionParser.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/ExpressionParser.cs @@ -6,2260 +6,13 @@ using umbraco.MacroEngines; namespace System.Linq.Dynamic { - internal class ExpressionParser + internal class ExpressionParser : Umbraco.Core.Dynamics.ExpressionParser { - struct Token - { - public TokenId id; - public string text; - public int pos; - } - - enum TokenId - { - Unknown, - End, - Identifier, - StringLiteral, - IntegerLiteral, - RealLiteral, - Exclamation, - Percent, - Amphersand, - OpenParen, - CloseParen, - Asterisk, - Plus, - Comma, - Minus, - Dot, - Slash, - Colon, - LessThan, - Equal, - GreaterThan, - Question, - OpenBracket, - CloseBracket, - Bar, - ExclamationEqual, - DoubleAmphersand, - LessThanEqual, - LessGreater, - DoubleEqual, - GreaterThanEqual, - DoubleBar - } - - interface ILogicalSignatures - { - void F(bool x, bool y); - void F(bool? x, bool? y); - } - - interface IArithmeticSignatures - { - void F(int x, int y); - void F(uint x, uint y); - void F(long x, long y); - void F(ulong x, ulong y); - void F(float x, float y); - void F(double x, double y); - void F(decimal x, decimal y); - void F(int? x, int? y); - void F(uint? x, uint? y); - void F(long? x, long? y); - void F(ulong? x, ulong? y); - void F(float? x, float? y); - void F(double? x, double? y); - void F(decimal? x, decimal? y); - } - - interface IRelationalSignatures : IArithmeticSignatures - { - void F(string x, string y); - void F(char x, char y); - void F(DateTime x, DateTime y); - void F(TimeSpan x, TimeSpan y); - void F(char? x, char? y); - void F(DateTime? x, DateTime? y); - void F(TimeSpan? x, TimeSpan? y); - } - - interface IEqualitySignatures : IRelationalSignatures - { - void F(bool x, bool y); - void F(bool? x, bool? y); - } - - interface IAddSignatures : IArithmeticSignatures - { - void F(DateTime x, TimeSpan y); - void F(TimeSpan x, TimeSpan y); - void F(DateTime? x, TimeSpan? y); - void F(TimeSpan? x, TimeSpan? y); - } - - interface ISubtractSignatures : IAddSignatures - { - void F(DateTime x, DateTime y); - void F(DateTime? x, DateTime? y); - } - - interface INegationSignatures - { - void F(int x); - void F(long x); - void F(float x); - void F(double x); - void F(decimal x); - void F(int? x); - void F(long? x); - void F(float? x); - void F(double? x); - void F(decimal? x); - } - - interface INotSignatures - { - void F(bool x); - void F(bool? x); - } - - interface IEnumerableSignatures - { - void Where(bool predicate); - void Any(); - void Any(bool predicate); - void All(bool predicate); - void Count(); - void Count(bool predicate); - void Min(object selector); - void Max(object selector); - void Sum(int selector); - void Sum(int? selector); - void Sum(long selector); - void Sum(long? selector); - void Sum(float selector); - void Sum(float? selector); - void Sum(double selector); - void Sum(double? selector); - void Sum(decimal selector); - void Sum(decimal? selector); - void Average(int selector); - void Average(int? selector); - void Average(long selector); - void Average(long? selector); - void Average(float selector); - void Average(float? selector); - void Average(double selector); - void Average(double? selector); - void Average(decimal selector); - void Average(decimal? selector); - } - - static readonly Type[] predefinedTypes = { - typeof(Object), - typeof(Boolean), - typeof(Char), - typeof(String), - typeof(SByte), - typeof(Byte), - typeof(Int16), - typeof(UInt16), - typeof(Int32), - typeof(UInt32), - typeof(Int64), - typeof(UInt64), - typeof(Single), - typeof(Double), - typeof(Decimal), - typeof(DateTime), - typeof(TimeSpan), - typeof(Guid), - typeof(Math), - typeof(Convert) - }; - - static readonly Expression trueLiteral = Expression.Constant(true); - static readonly Expression falseLiteral = Expression.Constant(false); - static readonly Expression nullLiteral = Expression.Constant(null); - - static readonly string keywordIt = "it"; - static readonly string keywordIif = "iif"; - static readonly string keywordNew = "new"; - - static Dictionary keywords; - - Dictionary symbols; - IDictionary externals; - Dictionary literals; - ParameterExpression it; - string text; - int textPos; - int textLen; - char ch; - Token token; - public ExpressionParser(ParameterExpression[] parameters, string expression, object[] values) + : base(parameters, expression, values) { - if (expression == null) throw new ArgumentNullException("expression"); - if (keywords == null) keywords = CreateKeywords(); - symbols = new Dictionary(StringComparer.OrdinalIgnoreCase); - literals = new Dictionary(); - if (parameters != null) ProcessParameters(parameters); - if (values != null) ProcessValues(values); - text = expression; - textLen = text.Length; - SetTextPos(0); - NextToken(); - } - - void ProcessParameters(ParameterExpression[] parameters) - { - foreach (ParameterExpression pe in parameters) - if (!String.IsNullOrEmpty(pe.Name)) - AddSymbol(pe.Name, pe); - if (parameters.Length == 1 && String.IsNullOrEmpty(parameters[0].Name)) - it = parameters[0]; - } - - void ProcessValues(object[] values) - { - for (int i = 0; i < values.Length; i++) - { - object value = values[i]; - if (i == values.Length - 1 && value is IDictionary) - { - externals = (IDictionary)value; - } - else - { - AddSymbol("@" + i.ToString(System.Globalization.CultureInfo.InvariantCulture), value); - } - } - } - - void AddSymbol(string name, object value) - { - if (symbols.ContainsKey(name)) - throw ParseError(Res.DuplicateIdentifier, name); - symbols.Add(name, value); - } - - public Expression Parse(Type resultType) - { - int exprPos = token.pos; - Expression expr = ParseExpression(); - if (resultType != null) - if ((expr = PromoteExpression(expr, resultType, true)) == null) - throw ParseError(exprPos, Res.ExpressionTypeMismatch, GetTypeName(resultType)); - ValidateToken(TokenId.End, Res.SyntaxError); - return expr; - } - -#pragma warning disable 0219 - public IEnumerable ParseOrdering() - { - List orderings = new List(); - while (true) - { - Expression expr = ParseExpression(); - bool ascending = true; - if (TokenIdentifierIs("asc") || TokenIdentifierIs("ascending")) - { - NextToken(); - } - else if (TokenIdentifierIs("desc") || TokenIdentifierIs("descending")) - { - NextToken(); - ascending = false; - } - orderings.Add(new DynamicOrdering { Selector = expr, Ascending = ascending }); - if (token.id != TokenId.Comma) break; - NextToken(); - } - ValidateToken(TokenId.End, Res.SyntaxError); - return orderings; - } -#pragma warning restore 0219 - - // ?: operator - Expression ParseExpression() - { - int errorPos = token.pos; - Expression expr = ParseLogicalOr(); - if (token.id == TokenId.Question) - { - NextToken(); - Expression expr1 = ParseExpression(); - ValidateToken(TokenId.Colon, Res.ColonExpected); - NextToken(); - Expression expr2 = ParseExpression(); - expr = GenerateConditional(expr, expr1, expr2, errorPos); - } - return expr; - } - - // ||, or operator - Expression ParseLogicalOr() - { - Expression left = ParseLogicalAnd(); - while (token.id == TokenId.DoubleBar || TokenIdentifierIs("or")) - { - Token op = token; - NextToken(); - Expression right = ParseLogicalAnd(); - CheckAndPromoteOperands(typeof(ILogicalSignatures), op.text, ref left, ref right, op.pos); - left = HandleDynamicNodeLambdas(ExpressionType.OrElse, left, right); - } - return left; - } - - // &&, and operator - Expression ParseLogicalAnd() - { - Expression left = ParseComparison(); - while (token.id == TokenId.DoubleAmphersand || TokenIdentifierIs("and")) - { - Token op = token; - NextToken(); - Expression right = ParseComparison(); - CheckAndPromoteOperands(typeof(ILogicalSignatures), op.text, ref left, ref right, op.pos); - left = HandleDynamicNodeLambdas(ExpressionType.AndAlso, left, right); - } - return left; - } - - // =, ==, !=, <>, >, >=, <, <= operators - Expression ParseComparison() - { - Expression left = ParseAdditive(); - while (token.id == TokenId.Equal || token.id == TokenId.DoubleEqual || - token.id == TokenId.ExclamationEqual || token.id == TokenId.LessGreater || - token.id == TokenId.GreaterThan || token.id == TokenId.GreaterThanEqual || - token.id == TokenId.LessThan || token.id == TokenId.LessThanEqual) - { - Token op = token; - NextToken(); - Expression right = ParseAdditive(); - bool isEquality = op.id == TokenId.Equal || op.id == TokenId.DoubleEqual || - op.id == TokenId.ExclamationEqual || op.id == TokenId.LessGreater; - if (isEquality && !left.Type.IsValueType && !right.Type.IsValueType) - { - if (left.Type != right.Type) - { - if (left.Type.IsAssignableFrom(right.Type)) - { - right = Expression.Convert(right, left.Type); - } - else if (right.Type.IsAssignableFrom(left.Type)) - { - left = Expression.Convert(left, right.Type); - } - else if (left is LambdaExpression || right is LambdaExpression) - { - //do nothing here (but further down we'll handle the lambdaexpression) - } - else - { - throw IncompatibleOperandsError(op.text, left, right, op.pos); - } - } - } - else if (IsEnumType(left.Type) || IsEnumType(right.Type)) - { - if (left.Type != right.Type) - { - Expression e; - if ((e = PromoteExpression(right, left.Type, true)) != null) - { - right = e; - } - else if ((e = PromoteExpression(left, right.Type, true)) != null) - { - left = e; - } - else - { - throw IncompatibleOperandsError(op.text, left, right, op.pos); - } - } - } - else - { - CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures), - op.text, ref left, ref right, op.pos); - } - switch (op.id) - { - case TokenId.Equal: - case TokenId.DoubleEqual: - left = HandleDynamicNodeLambdas(ExpressionType.Equal, left, right); - break; - case TokenId.ExclamationEqual: - case TokenId.LessGreater: - left = HandleDynamicNodeLambdas(ExpressionType.NotEqual, left, right); - break; - case TokenId.GreaterThan: - left = HandleDynamicNodeLambdas(ExpressionType.GreaterThan, left, right); - break; - case TokenId.GreaterThanEqual: - left = HandleDynamicNodeLambdas(ExpressionType.GreaterThanOrEqual, left, right); - break; - case TokenId.LessThan: - left = HandleDynamicNodeLambdas(ExpressionType.LessThan, left, right); - break; - case TokenId.LessThanEqual: - left = HandleDynamicNodeLambdas(ExpressionType.LessThanOrEqual, left, right); - break; - } - } - return left; - } - - // +, -, & operators - Expression ParseAdditive() - { - Expression left = ParseMultiplicative(); - while (token.id == TokenId.Plus || token.id == TokenId.Minus || - token.id == TokenId.Amphersand) - { - Token op = token; - NextToken(); - Expression right = ParseMultiplicative(); - switch (op.id) - { - case TokenId.Plus: - if (left.Type == typeof(string) || right.Type == typeof(string)) - goto case TokenId.Amphersand; - CheckAndPromoteOperands(typeof(IAddSignatures), op.text, ref left, ref right, op.pos); - left = GenerateAdd(left, right); - break; - case TokenId.Minus: - CheckAndPromoteOperands(typeof(ISubtractSignatures), op.text, ref left, ref right, op.pos); - left = GenerateSubtract(left, right); - break; - case TokenId.Amphersand: - left = GenerateStringConcat(left, right); - break; - } - } - return left; - } - - // *, /, %, mod operators - Expression ParseMultiplicative() - { - Expression left = ParseUnary(); - while (token.id == TokenId.Asterisk || token.id == TokenId.Slash || - token.id == TokenId.Percent || TokenIdentifierIs("mod")) - { - Token op = token; - NextToken(); - Expression right = ParseUnary(); - CheckAndPromoteOperands(typeof(IArithmeticSignatures), op.text, ref left, ref right, op.pos); - switch (op.id) - { - case TokenId.Asterisk: - left = Expression.Multiply(left, right); - break; - case TokenId.Slash: - left = Expression.Divide(left, right); - break; - case TokenId.Percent: - case TokenId.Identifier: - left = HandleDynamicNodeLambdas(ExpressionType.Modulo, left, right); - break; - } - } - return left; - } - - // -, !, not unary operators - Expression ParseUnary() - { - if (token.id == TokenId.Minus || token.id == TokenId.Exclamation || - TokenIdentifierIs("not")) - { - Token op = token; - NextToken(); - if (op.id == TokenId.Minus && (token.id == TokenId.IntegerLiteral || - token.id == TokenId.RealLiteral)) - { - token.text = "-" + token.text; - token.pos = op.pos; - return ParsePrimary(); - } - Expression expr = ParseUnary(); - if (op.id == TokenId.Minus) - { - CheckAndPromoteOperand(typeof(INegationSignatures), op.text, ref expr, op.pos); - expr = Expression.Negate(expr); - } - else - { - CheckAndPromoteOperand(typeof(INotSignatures), op.text, ref expr, op.pos); - if (expr is LambdaExpression) - { - ParameterExpression[] parameters = new ParameterExpression[(expr as LambdaExpression).Parameters.Count]; - (expr as LambdaExpression).Parameters.CopyTo(parameters, 0); - var invokedExpr = Expression.Invoke(expr, parameters); - var not = Expression.Not(Expression.TypeAs(invokedExpr, typeof(Nullable))); - expr = Expression.Lambda>( - Expression.Condition( - Expression.Property(not, "HasValue"), - Expression.Property(not, "Value"), - Expression.Constant(false, typeof(bool)) - ), parameters); - } - else - { - expr = Expression.Not(expr); - } - } - return expr; - } - return ParsePrimary(); - } - - Expression ParsePrimary() - { - Expression expr = ParsePrimaryStart(); - while (true) - { - if (token.id == TokenId.Dot) - { - NextToken(); - expr = ParseMemberAccess(null, expr); - } - else if (token.id == TokenId.OpenBracket) - { - expr = ParseElementAccess(expr); - } - else - { - break; - } - } - return expr; - } - - Expression ParsePrimaryStart() - { - switch (token.id) - { - case TokenId.Identifier: - return ParseIdentifier(); - case TokenId.StringLiteral: - return ParseStringLiteral(); - case TokenId.IntegerLiteral: - return ParseIntegerLiteral(); - case TokenId.RealLiteral: - return ParseRealLiteral(); - case TokenId.OpenParen: - return ParseParenExpression(); - default: - throw ParseError(Res.ExpressionExpected); - } - } - - Expression ParseStringLiteral() - { - ValidateToken(TokenId.StringLiteral); - char quote = token.text[0]; - string s = token.text.Substring(1, token.text.Length - 2); - int start = 0; - while (true) - { - int i = s.IndexOf(quote, start); - if (i < 0) break; - s = s.Remove(i, 1); - start = i + 1; - } - if (quote == '\'') - { - if (s.Length != 1) - throw ParseError(Res.InvalidCharacterLiteral); - NextToken(); - return CreateLiteral(s[0], s); - } - NextToken(); - return CreateLiteral(s, s); - } - - Expression ParseIntegerLiteral() - { - ValidateToken(TokenId.IntegerLiteral); - string text = token.text; - if (text[0] != '-') - { - ulong value; - if (!UInt64.TryParse(text, out value)) - throw ParseError(Res.InvalidIntegerLiteral, text); - NextToken(); - if (value <= (ulong)Int32.MaxValue) return CreateLiteral((int)value, text); - if (value <= (ulong)UInt32.MaxValue) return CreateLiteral((uint)value, text); - if (value <= (ulong)Int64.MaxValue) return CreateLiteral((long)value, text); - return CreateLiteral(value, text); - } - else - { - long value; - if (!Int64.TryParse(text, out value)) - throw ParseError(Res.InvalidIntegerLiteral, text); - NextToken(); - if (value >= Int32.MinValue && value <= Int32.MaxValue) - return CreateLiteral((int)value, text); - return CreateLiteral(value, text); - } - } - - Expression ParseRealLiteral() - { - ValidateToken(TokenId.RealLiteral); - string text = token.text; - object value = null; - char last = text[text.Length - 1]; - if (last == 'F' || last == 'f') - { - float f; - if (Single.TryParse(text.Substring(0, text.Length - 1), out f)) value = f; - } - else - { - double d; - if (Double.TryParse(text, out d)) value = d; - } - if (value == null) throw ParseError(Res.InvalidRealLiteral, text); - NextToken(); - return CreateLiteral(value, text); - } - - Expression CreateLiteral(object value, string text) - { - ConstantExpression expr = Expression.Constant(value); - literals.Add(expr, text); - return expr; - } - - Expression ParseParenExpression() - { - ValidateToken(TokenId.OpenParen, Res.OpenParenExpected); - NextToken(); - Expression e = ParseExpression(); - ValidateToken(TokenId.CloseParen, Res.CloseParenOrOperatorExpected); - NextToken(); - return e; - } - - Expression ParseIdentifier() - { - ValidateToken(TokenId.Identifier); - object value; - if (keywords.TryGetValue(token.text, out value)) - { - if (value is Type) return ParseTypeAccess((Type)value); - if (value == (object)keywordIt) return ParseIt(); - if (value == (object)keywordIif) return ParseIif(); - if (value == (object)keywordNew) return ParseNew(); - NextToken(); - return (Expression)value; - } - if (symbols.TryGetValue(token.text, out value) || - externals != null && externals.TryGetValue(token.text, out value)) - { - Expression expr = value as Expression; - if (expr == null) - { - expr = Expression.Constant(value); - } - else - { - LambdaExpression lambda = expr as LambdaExpression; - if (lambda != null) return ParseLambdaInvocation(lambda); - } - NextToken(); - return expr; - } - if (it != null) return ParseMemberAccess(null, it); - throw ParseError(Res.UnknownIdentifier, token.text); - } - - Expression ParseIt() - { - if (it == null) - throw ParseError(Res.NoItInScope); - NextToken(); - return it; - } - - Expression ParseIif() - { - int errorPos = token.pos; - NextToken(); - Expression[] args = ParseArgumentList(); - if (args.Length != 3) - throw ParseError(errorPos, Res.IifRequiresThreeArgs); - return GenerateConditional(args[0], args[1], args[2], errorPos); - } - - Expression GenerateConditional(Expression test, Expression expr1, Expression expr2, int errorPos) - { - if (test.Type != typeof(bool)) - throw ParseError(errorPos, Res.FirstExprMustBeBool); - if (expr1.Type != expr2.Type) - { - Expression expr1as2 = expr2 != nullLiteral ? PromoteExpression(expr1, expr2.Type, true) : null; - Expression expr2as1 = expr1 != nullLiteral ? PromoteExpression(expr2, expr1.Type, true) : null; - if (expr1as2 != null && expr2as1 == null) - { - expr1 = expr1as2; - } - else if (expr2as1 != null && expr1as2 == null) - { - expr2 = expr2as1; - } - else - { - string type1 = expr1 != nullLiteral ? expr1.Type.Name : "null"; - string type2 = expr2 != nullLiteral ? expr2.Type.Name : "null"; - if (expr1as2 != null && expr2as1 != null) - throw ParseError(errorPos, Res.BothTypesConvertToOther, type1, type2); - throw ParseError(errorPos, Res.NeitherTypeConvertsToOther, type1, type2); - } - } - return Expression.Condition(test, expr1, expr2); - } - - Expression ParseNew() - { - NextToken(); - ValidateToken(TokenId.OpenParen, Res.OpenParenExpected); - NextToken(); - List properties = new List(); - List expressions = new List(); - while (true) - { - int exprPos = token.pos; - Expression expr = ParseExpression(); - string propName; - if (TokenIdentifierIs("as")) - { - NextToken(); - propName = GetIdentifier(); - NextToken(); - } - else - { - MemberExpression me = expr as MemberExpression; - if (me == null) throw ParseError(exprPos, Res.MissingAsClause); - propName = me.Member.Name; - } - expressions.Add(expr); - properties.Add(new DynamicProperty(propName, expr.Type)); - if (token.id != TokenId.Comma) break; - NextToken(); - } - ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected); - NextToken(); - Type type = DynamicExpression.CreateClass(properties); - MemberBinding[] bindings = new MemberBinding[properties.Count]; - for (int i = 0; i < bindings.Length; i++) - bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]); - return Expression.MemberInit(Expression.New(type), bindings); - } - - Expression ParseLambdaInvocation(LambdaExpression lambda) - { - int errorPos = token.pos; - NextToken(); - Expression[] args = ParseArgumentList(); - MethodBase method; - if (FindMethod(lambda.Type, "Invoke", false, args, out method) != 1) - throw ParseError(errorPos, Res.ArgsIncompatibleWithLambda); - return Expression.Invoke(lambda, args); - } - - Expression ParseTypeAccess(Type type) - { - int errorPos = token.pos; - NextToken(); - if (token.id == TokenId.Question) - { - if (!type.IsValueType || IsNullableType(type)) - throw ParseError(errorPos, Res.TypeHasNoNullableForm, GetTypeName(type)); - type = typeof(Nullable<>).MakeGenericType(type); - NextToken(); - } - if (token.id == TokenId.OpenParen) - { - Expression[] args = ParseArgumentList(); - MethodBase method; - switch (FindBestMethod(type.GetConstructors(), args, out method)) - { - case 0: - if (args.Length == 1) - return GenerateConversion(args[0], type, errorPos); - throw ParseError(errorPos, Res.NoMatchingConstructor, GetTypeName(type)); - case 1: - return Expression.New((ConstructorInfo)method, args); - default: - throw ParseError(errorPos, Res.AmbiguousConstructorInvocation, GetTypeName(type)); - } - } - ValidateToken(TokenId.Dot, Res.DotOrOpenParenExpected); - NextToken(); - return ParseMemberAccess(type, null); - } - - Expression GenerateConversion(Expression expr, Type type, int errorPos) - { - Type exprType = expr.Type; - if (exprType == type) return expr; - if (exprType.IsValueType && type.IsValueType) - { - if ((IsNullableType(exprType) || IsNullableType(type)) && - GetNonNullableType(exprType) == GetNonNullableType(type)) - return Expression.Convert(expr, type); - if ((IsNumericType(exprType) || IsEnumType(exprType)) && - (IsNumericType(type)) || IsEnumType(type)) - return Expression.ConvertChecked(expr, type); - } - if (exprType.IsAssignableFrom(type) || type.IsAssignableFrom(exprType) || - exprType.IsInterface || type.IsInterface) - return Expression.Convert(expr, type); - throw ParseError(errorPos, Res.CannotConvertValue, - GetTypeName(exprType), GetTypeName(type)); - } - - Expression ParseMemberAccess(Type type, Expression instance) - { - if (instance != null) type = instance.Type; - int errorPos = token.pos; - string id = GetIdentifier(); - NextToken(); - if (token.id == TokenId.OpenParen) - { - if (instance != null && type != typeof(string)) - { - Type enumerableType = FindGenericType(typeof(IEnumerable<>), type); - if (enumerableType != null) - { - Type elementType = enumerableType.GetGenericArguments()[0]; - return ParseAggregate(instance, elementType, id, errorPos); - } - } - Expression[] args = ParseArgumentList(); - MethodBase mb; - LambdaExpression instanceAsString = null; - ParameterExpression instanceExpression = Expression.Parameter(typeof(DynamicNode), "instance"); - if (type.IsGenericType && type != typeof(string)) - { - var typeArgs = type.GetGenericArguments(); - if (typeArgs[0] == typeof(DynamicNode)) - { - if (instance != null && instance is LambdaExpression) - { - if (typeArgs[1] == typeof(object)) - { - instanceAsString = StringFormat(instance as LambdaExpression, instanceExpression); - type = typeof(string); - } - if (typeArgs[1] == typeof(string)) - { - instanceAsString = instance as LambdaExpression; - type = typeof(string); - } - } - } - } - switch (FindMethod(type, id, instance == null, args, out mb)) - { - case 0: - //not found - if (type == typeof(string) && instanceAsString != null) - { - Expression[] newArgs = (new List() { Expression.Invoke(instanceAsString, instanceExpression) }).Concat(args).ToArray(); - mb = ExtensionMethodFinder.FindExtensionMethod(typeof(string), newArgs, id, true); - if (mb != null) - { - return CallMethodOnDynamicNode(instance, newArgs, instanceAsString, instanceExpression, (MethodInfo)mb, true); - } - } - if (type == typeof(string) && instanceAsString == null && instance is MemberExpression) - { - Expression[] newArgs = (new List() { instance }).Concat(args).ToArray(); - mb = ExtensionMethodFinder.FindExtensionMethod(typeof(string), newArgs, id, true); - if (mb != null) - { - return Expression.Call(null, (MethodInfo)mb, newArgs); - } - } - - throw ParseError(errorPos, Res.NoApplicableMethod, - id, GetTypeName(type)); - case 1: - MethodInfo method = (MethodInfo)mb; - if (!IsPredefinedType(method.DeclaringType)) - throw ParseError(errorPos, Res.MethodsAreInaccessible, GetTypeName(method.DeclaringType)); - if (method.ReturnType == typeof(void)) - throw ParseError(errorPos, Res.MethodIsVoid, - id, GetTypeName(method.DeclaringType)); - if (instanceAsString != null) - { - return CallMethodOnDynamicNode(instance, args, instanceAsString, instanceExpression, method, false); - } - return Expression.Call(instance, (MethodInfo)method, args); - default: - throw ParseError(errorPos, Res.AmbiguousMethodInvocation, - id, GetTypeName(type)); - } - } - else - { - //Looks for a member on the type, but above, we're rerouting that into TryGetMember - MemberInfo member = FindPropertyOrField(type, id, instance == null); - if (member == null) - { - if (typeof(DynamicObject).IsAssignableFrom(type)) - { - //We are going to generate a dynamic method by hand coding the expression tree - //this will invoke TryGetMember (but wrapped in an expression tree) - //so that when it's evaluated, DynamicNode should be supported - - ParameterExpression instanceExpression = Expression.Parameter(typeof(DynamicNode), "instance"); - ParameterExpression convertDynamicNullToBooleanFalse = Expression.Parameter(typeof(bool), "convertDynamicNullToBooleanFalse"); - ParameterExpression result = Expression.Parameter(typeof(object), "result"); - ParameterExpression binder = Expression.Variable(typeof(DynamicQueryableGetMemberBinder), "binder"); - ParameterExpression ignoreCase = Expression.Variable(typeof(bool), "ignoreCase"); - ConstructorInfo getMemberBinderConstructor = typeof(DynamicQueryableGetMemberBinder).GetConstructor(new Type[] { typeof(string), typeof(bool) }); - LabelTarget blockReturnLabel = Expression.Label(typeof(object)); - MethodInfo method = typeof(DynamicNode).GetMethod("TryGetMember"); - - BlockExpression block = Expression.Block( - typeof(object), - new[] { ignoreCase, binder, result, convertDynamicNullToBooleanFalse }, - Expression.Assign(convertDynamicNullToBooleanFalse, Expression.Constant(DynamicExpression.ConvertDynamicNullToBooleanFalse, typeof(bool))), - Expression.Assign(ignoreCase, Expression.Constant(false, typeof(bool))), - Expression.Assign(binder, Expression.New(getMemberBinderConstructor, Expression.Constant(id, typeof(string)), ignoreCase)), - Expression.Assign(result, Expression.Constant(null)), - Expression.IfThen(Expression.NotEqual(Expression.Constant(null), instanceExpression), - Expression.Call(instanceExpression, method, binder, result)), - Expression.IfThen( - Expression.AndAlso( - Expression.TypeEqual(result, typeof(DynamicNull)), - Expression.Equal(convertDynamicNullToBooleanFalse, Expression.Constant(true, typeof(bool))) - ), - Expression.Assign(result, Expression.Constant(false, typeof(object))) - ), - Expression.Return(blockReturnLabel, result), - Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object))) - ); - LambdaExpression lax = Expression.Lambda>(block, instanceExpression); - return lax; - } - if (typeof(Func).IsAssignableFrom(type)) - { - //accessing a property off an already resolved DynamicNode TryGetMember call - //e.g. uBlogsyPostDate.Date - //SD: Removed the NonPublic accessor here because this will never work in medium trust, wondering why it is NonPublic vs Public ? Have changed to Public. - //MethodInfo ReflectPropertyValue = this.GetType().GetMethod("ReflectPropertyValue", BindingFlags.NonPublic | BindingFlags.Static); - MethodInfo ReflectPropertyValue = this.GetType().GetMethod("ReflectPropertyValue", BindingFlags.Public | BindingFlags.Static); - ParameterExpression convertDynamicNullToBooleanFalse = Expression.Parameter(typeof(bool), "convertDynamicNullToBooleanFalse"); - ParameterExpression result = Expression.Parameter(typeof(object), "result"); - ParameterExpression idParam = Expression.Parameter(typeof(string), "id"); - ParameterExpression lambdaResult = Expression.Parameter(typeof(object), "lambdaResult"); - ParameterExpression lambdaInstanceExpression = Expression.Parameter(typeof(DynamicNode), "lambdaInstanceExpression"); - ParameterExpression instanceExpression = Expression.Parameter(typeof(Func), "instance"); - LabelTarget blockReturnLabel = Expression.Label(typeof(object)); - - BlockExpression block = Expression.Block( - typeof(object), - new[] { lambdaResult, result, idParam, convertDynamicNullToBooleanFalse }, - Expression.Assign(convertDynamicNullToBooleanFalse, Expression.Constant(DynamicExpression.ConvertDynamicNullToBooleanFalse, typeof(bool))), - Expression.Assign(lambdaResult, Expression.Invoke(instance, lambdaInstanceExpression)), - Expression.Assign(result, Expression.Call(ReflectPropertyValue, lambdaResult, Expression.Constant(id))), - Expression.IfThen( - Expression.AndAlso( - Expression.TypeEqual(result, typeof(DynamicNull)), - Expression.Equal(convertDynamicNullToBooleanFalse, Expression.Constant(true, typeof(bool))) - ), - Expression.Assign(result, Expression.Constant(false, typeof(object))) - ), - Expression.Return(blockReturnLabel, result), - Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object))) - ); - LambdaExpression lax = Expression.Lambda>(block, lambdaInstanceExpression); - return lax; - } - } - else - { - return member is PropertyInfo ? - Expression.Property(instance, (PropertyInfo)member) : - Expression.Field(instance, (FieldInfo)member); - } - throw ParseError(errorPos, Res.UnknownPropertyOrField, - id, GetTypeName(type)); - - } - } - static object ReflectPropertyValue(object o, string name) - { - PropertyInfo propertyInfo = o.GetType().GetProperty(name); - if (propertyInfo != null) - { - object result = propertyInfo.GetValue(o, null); - return result; - } - return null; - } - private static Expression CallMethodOnDynamicNode(Expression instance, Expression[] args, LambdaExpression instanceAsString, ParameterExpression instanceExpression, MethodInfo method, bool isStatic) - { - ConstantExpression defaultReturnValue = Expression.Constant(null, typeof(object)); - Type methodReturnType = method.ReturnType; - switch (methodReturnType.Name) - { - case "String": - defaultReturnValue = Expression.Constant(null, typeof(string)); - break; - case "Int32": - defaultReturnValue = Expression.Constant(0, typeof(int)); - break; - case "Boolean": - defaultReturnValue = Expression.Constant(false, typeof(bool)); - break; - } - ParameterExpression result = Expression.Parameter(method.ReturnType, "result"); - LabelTarget blockReturnLabel = Expression.Label(method.ReturnType); - BlockExpression block = Expression.Block( - method.ReturnType, - new[] { result }, - Expression.Assign(result, - Expression.Call( - isStatic ? null : Expression.Invoke(instanceAsString, instanceExpression), - method, - args) - ), - Expression.Return(blockReturnLabel, result), - Expression.Label(blockReturnLabel, defaultReturnValue) - ); - - switch (methodReturnType.Name) - { - case "String": - return Expression.Lambda>(block, instanceExpression); - case "Int32": - return Expression.Lambda>(block, instanceExpression); - case "Boolean": - return Expression.Lambda>(block, instanceExpression); - } - return Expression.Call(instance, (MethodInfo)method, args); - } - - static Type FindGenericType(Type generic, Type type) - { - while (type != null && type != typeof(object)) - { - if (type.IsGenericType && type.GetGenericTypeDefinition() == generic) return type; - if (generic.IsInterface) - { - foreach (Type intfType in type.GetInterfaces()) - { - Type found = FindGenericType(generic, intfType); - if (found != null) return found; - } - } - type = type.BaseType; - } - return null; - } - LambdaExpression StringFormat(LambdaExpression lax, ParameterExpression instanceExpression) - { - ParameterExpression cresult = Expression.Parameter(typeof(string), "cresult"); - ParameterExpression temp = Expression.Parameter(typeof(object), "temp"); - ParameterExpression stemp = Expression.Parameter(typeof(string), "string"); - LabelTarget cblockReturnLabel = Expression.Label(typeof(string)); - - MethodInfo stringFormat = typeof(string).GetMethod("Format", new Type[] { typeof(string), typeof(object) }); - BlockExpression cblock = Expression.Block( - typeof(string), - new[] { cresult, temp }, - Expression.Assign(temp, Expression.Invoke(lax, instanceExpression)), - Expression.Assign(cresult, Expression.Call(stringFormat, Expression.Constant("{0}"), temp)), - Expression.Return(cblockReturnLabel, cresult), - Expression.Label(cblockReturnLabel, Expression.Constant(null, typeof(string)))); - - LambdaExpression lax2 = Expression.Lambda>(cblock, instanceExpression); - var expression = Expression.Lambda>(cblock, instanceExpression); - return expression; - - } - Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos) - { - ParameterExpression outerIt = it; - ParameterExpression innerIt = Expression.Parameter(elementType, ""); - it = innerIt; - Expression[] args = ParseArgumentList(); - it = outerIt; - MethodBase signature; - if (FindMethod(typeof(IEnumerableSignatures), methodName, false, args, out signature) != 1) - throw ParseError(errorPos, Res.NoApplicableAggregate, methodName); - Type[] typeArgs; - if (signature.Name == "Min" || signature.Name == "Max") - { - typeArgs = new Type[] { elementType, args[0].Type }; - } - else - { - typeArgs = new Type[] { elementType }; - } - if (args.Length == 0) - { - args = new Expression[] { instance }; - } - else - { - args = new Expression[] { instance, Expression.Lambda(args[0], innerIt) }; - } - return Expression.Call(typeof(Enumerable), signature.Name, typeArgs, args); - } - - Expression[] ParseArgumentList() - { - ValidateToken(TokenId.OpenParen, Res.OpenParenExpected); - NextToken(); - Expression[] args = token.id != TokenId.CloseParen ? ParseArguments() : new Expression[0]; - ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected); - NextToken(); - return args; - } - - Expression[] ParseArguments() - { - List argList = new List(); - while (true) - { - argList.Add(ParseExpression()); - if (token.id != TokenId.Comma) break; - NextToken(); - } - return argList.ToArray(); - } - - Expression ParseElementAccess(Expression expr) - { - int errorPos = token.pos; - ValidateToken(TokenId.OpenBracket, Res.OpenParenExpected); - NextToken(); - Expression[] args = ParseArguments(); - ValidateToken(TokenId.CloseBracket, Res.CloseBracketOrCommaExpected); - NextToken(); - if (expr.Type.IsArray) - { - if (expr.Type.GetArrayRank() != 1 || args.Length != 1) - throw ParseError(errorPos, Res.CannotIndexMultiDimArray); - Expression index = PromoteExpression(args[0], typeof(int), true); - if (index == null) - throw ParseError(errorPos, Res.InvalidIndex); - return Expression.ArrayIndex(expr, index); - } - else - { - MethodBase mb; - switch (FindIndexer(expr.Type, args, out mb)) - { - case 0: - throw ParseError(errorPos, Res.NoApplicableIndexer, - GetTypeName(expr.Type)); - case 1: - return Expression.Call(expr, (MethodInfo)mb, args); - default: - throw ParseError(errorPos, Res.AmbiguousIndexerInvocation, - GetTypeName(expr.Type)); - } - } - } - - static bool IsPredefinedType(Type type) - { - foreach (Type t in predefinedTypes) if (t == type) return true; - return false; - } - - static bool IsNullableType(Type type) - { - return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); - } - - static Type GetNonNullableType(Type type) - { - return IsNullableType(type) ? type.GetGenericArguments()[0] : type; - } - - static string GetTypeName(Type type) - { - Type baseType = GetNonNullableType(type); - string s = baseType.Name; - if (type != baseType) s += '?'; - return s; - } - - static bool IsNumericType(Type type) - { - return GetNumericTypeKind(type) != 0; - } - - static bool IsSignedIntegralType(Type type) - { - return GetNumericTypeKind(type) == 2; - } - - static bool IsUnsignedIntegralType(Type type) - { - return GetNumericTypeKind(type) == 3; - } - - static int GetNumericTypeKind(Type type) - { - type = GetNonNullableType(type); - if (type.IsEnum) return 0; - switch (Type.GetTypeCode(type)) - { - case TypeCode.Char: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - return 1; - case TypeCode.SByte: - case TypeCode.Int16: - case TypeCode.Int32: - case TypeCode.Int64: - return 2; - case TypeCode.Byte: - case TypeCode.UInt16: - case TypeCode.UInt32: - case TypeCode.UInt64: - return 3; - default: - return 0; - } - } - - static bool IsEnumType(Type type) - { - return GetNonNullableType(type).IsEnum; - } - - void CheckAndPromoteOperand(Type signatures, string opName, ref Expression expr, int errorPos) - { - Expression[] args = new Expression[] { expr }; - MethodBase method; - if (FindMethod(signatures, "F", false, args, out method) != 1) - throw ParseError(errorPos, Res.IncompatibleOperand, - opName, GetTypeName(args[0].Type)); - expr = args[0]; - } - - void CheckAndPromoteOperands(Type signatures, string opName, ref Expression left, ref Expression right, int errorPos) - { - Expression[] args = new Expression[] { left, right }; - MethodBase method; - if (FindMethod(signatures, "F", false, args, out method) != 1) - throw IncompatibleOperandsError(opName, left, right, errorPos); - left = args[0]; - right = args[1]; - } - - Exception IncompatibleOperandsError(string opName, Expression left, Expression right, int pos) - { - return ParseError(pos, Res.IncompatibleOperands, - opName, GetTypeName(left.Type), GetTypeName(right.Type)); - } - - MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess) - { - BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly | - (staticAccess ? BindingFlags.Static : BindingFlags.Instance); - foreach (Type t in SelfAndBaseTypes(type)) - { - MemberInfo[] members = t.FindMembers(MemberTypes.Property | MemberTypes.Field, - flags, Type.FilterNameIgnoreCase, memberName); - if (members.Length != 0) return members[0]; - } - return null; - } - - int FindMethod(Type type, string methodName, bool staticAccess, Expression[] args, out MethodBase method) - { - BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly | - (staticAccess ? BindingFlags.Static : BindingFlags.Instance); - foreach (Type t in SelfAndBaseTypes(type)) - { - MemberInfo[] members = t.FindMembers(MemberTypes.Method, - flags, Type.FilterNameIgnoreCase, methodName); - int count = FindBestMethod(members.Cast(), args, out method); - if (count != 0) return count; - } - method = null; - return 0; - } - - int FindIndexer(Type type, Expression[] args, out MethodBase method) - { - foreach (Type t in SelfAndBaseTypes(type)) - { - MemberInfo[] members = t.GetDefaultMembers(); - if (members.Length != 0) - { - IEnumerable methods = members. - OfType(). - Select(p => (MethodBase)p.GetGetMethod()). - Where(m => m != null); - int count = FindBestMethod(methods, args, out method); - if (count != 0) return count; - } - } - method = null; - return 0; - } - - static IEnumerable SelfAndBaseTypes(Type type) - { - if (type.IsInterface) - { - List types = new List(); - AddInterface(types, type); - return types; - } - return SelfAndBaseClasses(type); - } - - static IEnumerable SelfAndBaseClasses(Type type) - { - while (type != null) - { - yield return type; - type = type.BaseType; - } - } - - static void AddInterface(List types, Type type) - { - if (!types.Contains(type)) - { - types.Add(type); - foreach (Type t in type.GetInterfaces()) AddInterface(types, t); - } - } - - class MethodData - { - public MethodBase MethodBase; - public ParameterInfo[] Parameters; - public Expression[] Args; - } - - int FindBestMethod(IEnumerable methods, Expression[] args, out MethodBase method) - { - MethodData[] applicable = methods. - Select(m => new MethodData { MethodBase = m, Parameters = m.GetParameters() }). - Where(m => IsApplicable(m, args)). - ToArray(); - if (applicable.Length > 1) - { - applicable = applicable. - Where(m => applicable.All(n => m == n || IsBetterThan(args, m, n))). - ToArray(); - } - if (applicable.Length == 1) - { - MethodData md = applicable[0]; - for (int i = 0; i < args.Length; i++) args[i] = md.Args[i]; - method = md.MethodBase; - } - else - { - method = null; - } - return applicable.Length; - } - - bool IsApplicable(MethodData method, Expression[] args) - { - if (method.Parameters.Length != args.Length) return false; - Expression[] promotedArgs = new Expression[args.Length]; - for (int i = 0; i < args.Length; i++) - { - ParameterInfo pi = method.Parameters[i]; - if (pi.IsOut) return false; - Expression promoted = PromoteExpression(args[i], pi.ParameterType, false); - if (promoted == null) return false; - promotedArgs[i] = promoted; - } - method.Args = promotedArgs; - return true; - } - - Expression PromoteExpression(Expression expr, Type type, bool exact) - { - //if the type of the expression is the correct target type, just return it here - if (expr.Type == type) return expr; - //if the type of the expression is a func - invokable returning object, - //we are going to return it here, because we can get the real value when we actually have the instance - //if (typeof(Func).IsAssignableFrom(expr.Type)) return expr; - if (expr is LambdaExpression && ((LambdaExpression)expr).Parameters.Count > 0 && ((LambdaExpression)expr).Parameters[0].Type == typeof(DynamicNode)) - { - return expr; - } - if (expr is ConstantExpression) - { - ConstantExpression ce = (ConstantExpression)expr; - if (ce == nullLiteral) - { - if (!type.IsValueType || IsNullableType(type)) - return Expression.Constant(null, type); - } - else - { - string text; - if (literals.TryGetValue(ce, out text)) - { - Type target = GetNonNullableType(type); - Object value = null; - switch (Type.GetTypeCode(ce.Type)) - { - case TypeCode.Int32: - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: - value = ParseNumber(text, target); - break; - case TypeCode.Double: - if (target == typeof(decimal)) value = ParseNumber(text, target); - break; - case TypeCode.String: - value = ParseEnum(text, target); - break; - } - if (value != null) - return Expression.Constant(value, type); - } - } - } - if (IsCompatibleWith(expr.Type, type)) - { - if (type.IsValueType || exact) return Expression.Convert(expr, type); - return expr; - } - return null; - } - - static object ParseNumber(string text, Type type) - { - switch (Type.GetTypeCode(GetNonNullableType(type))) - { - case TypeCode.SByte: - sbyte sb; - if (sbyte.TryParse(text, out sb)) return sb; - break; - case TypeCode.Byte: - byte b; - if (byte.TryParse(text, out b)) return b; - break; - case TypeCode.Int16: - short s; - if (short.TryParse(text, out s)) return s; - break; - case TypeCode.UInt16: - ushort us; - if (ushort.TryParse(text, out us)) return us; - break; - case TypeCode.Int32: - int i; - if (int.TryParse(text, out i)) return i; - break; - case TypeCode.UInt32: - uint ui; - if (uint.TryParse(text, out ui)) return ui; - break; - case TypeCode.Int64: - long l; - if (long.TryParse(text, out l)) return l; - break; - case TypeCode.UInt64: - ulong ul; - if (ulong.TryParse(text, out ul)) return ul; - break; - case TypeCode.Single: - float f; - if (float.TryParse(text, out f)) return f; - break; - case TypeCode.Double: - double d; - if (double.TryParse(text, out d)) return d; - break; - case TypeCode.Decimal: - decimal e; - if (decimal.TryParse(text, out e)) return e; - break; - } - return null; - } - - static object ParseEnum(string name, Type type) - { - if (type.IsEnum) - { - MemberInfo[] memberInfos = type.FindMembers(MemberTypes.Field, - BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static, - Type.FilterNameIgnoreCase, name); - if (memberInfos.Length != 0) return ((FieldInfo)memberInfos[0]).GetValue(null); - } - return null; - } - - static bool IsCompatibleWith(Type source, Type target) - { - if (source == target) return true; - if (!target.IsValueType) return target.IsAssignableFrom(source); - Type st = GetNonNullableType(source); - Type tt = GetNonNullableType(target); - if (st != source && tt == target) return false; - TypeCode sc = st.IsEnum ? TypeCode.Object : Type.GetTypeCode(st); - TypeCode tc = tt.IsEnum ? TypeCode.Object : Type.GetTypeCode(tt); - switch (sc) - { - case TypeCode.SByte: - switch (tc) - { - case TypeCode.SByte: - case TypeCode.Int16: - case TypeCode.Int32: - case TypeCode.Int64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - return true; - } - break; - case TypeCode.Byte: - switch (tc) - { - case TypeCode.Byte: - case TypeCode.Int16: - case TypeCode.UInt16: - case TypeCode.Int32: - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - return true; - } - break; - case TypeCode.Int16: - switch (tc) - { - case TypeCode.Int16: - case TypeCode.Int32: - case TypeCode.Int64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - return true; - } - break; - case TypeCode.UInt16: - switch (tc) - { - case TypeCode.UInt16: - case TypeCode.Int32: - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - return true; - } - break; - case TypeCode.Int32: - switch (tc) - { - case TypeCode.Int32: - case TypeCode.Int64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - return true; - } - break; - case TypeCode.UInt32: - switch (tc) - { - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - return true; - } - break; - case TypeCode.Int64: - switch (tc) - { - case TypeCode.Int64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - return true; - } - break; - case TypeCode.UInt64: - switch (tc) - { - case TypeCode.UInt64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - return true; - } - break; - case TypeCode.Single: - switch (tc) - { - case TypeCode.Single: - case TypeCode.Double: - return true; - } - break; - default: - if (st == tt) return true; - break; - } - return false; - } - - static bool IsBetterThan(Expression[] args, MethodData m1, MethodData m2) - { - bool better = false; - for (int i = 0; i < args.Length; i++) - { - int c = CompareConversions(args[i].Type, - m1.Parameters[i].ParameterType, - m2.Parameters[i].ParameterType); - if (c < 0) return false; - if (c > 0) better = true; - } - return better; - } - - // Return 1 if s -> t1 is a better conversion than s -> t2 - // Return -1 if s -> t2 is a better conversion than s -> t1 - // Return 0 if neither conversion is better - static int CompareConversions(Type s, Type t1, Type t2) - { - if (t1 == t2) return 0; - if (s == t1) return 1; - if (s == t2) return -1; - bool t1t2 = IsCompatibleWith(t1, t2); - bool t2t1 = IsCompatibleWith(t2, t1); - if (t1t2 && !t2t1) return 1; - if (t2t1 && !t1t2) return -1; - if (IsSignedIntegralType(t1) && IsUnsignedIntegralType(t2)) return 1; - if (IsSignedIntegralType(t2) && IsUnsignedIntegralType(t1)) return -1; - return 0; - } - - Expression GenerateEqual(Expression left, Expression right) - { - return HandleDynamicNodeLambdas(ExpressionType.Equal, left, right); - } - - private static Expression HandleDynamicNodeLambdas(ExpressionType expressionType, Expression left, Expression right) - { - bool leftIsLambda = false, rightIsLambda = false; - Expression innerLeft = null; - Expression innerRight = null; - UnaryExpression unboxedLeft = null, unboxedRight = null; - ParameterExpression[] parameters = null; - - if (left is LambdaExpression && (left as LambdaExpression).Type.GetGenericArguments().First() == typeof(DynamicNode)) - { - leftIsLambda = true; - } - - if (right is LambdaExpression && (right as LambdaExpression).Type.GetGenericArguments().First() == typeof(DynamicNode)) - { - rightIsLambda = true; - } - - if (leftIsLambda && !rightIsLambda) - { - parameters = new ParameterExpression[(left as LambdaExpression).Parameters.Count]; - (left as LambdaExpression).Parameters.CopyTo(parameters, 0); - if (right is ConstantExpression) - { - //left lambda, right constant - var invokedExpr = Expression.Invoke(left, (left as LambdaExpression).Parameters.Cast()); - innerLeft = Expression.Convert(invokedExpr, (right as ConstantExpression).Type); - } - if (leftIsLambda && !rightIsLambda && right is MemberExpression) - { - var invokedExpr = Expression.Invoke(left, (left as LambdaExpression).Parameters.Cast()); - innerLeft = Expression.Convert(invokedExpr, (right as MemberExpression).Type); - } - } - if (rightIsLambda && !leftIsLambda) - { - parameters = new ParameterExpression[(right as LambdaExpression).Parameters.Count]; - (right as LambdaExpression).Parameters.CopyTo(parameters, 0); - if (left is ConstantExpression) - { - //right lambda, left constant - var invokedExpr = Expression.Invoke(right, (right as LambdaExpression).Parameters.Cast()); - innerRight = Expression.Convert(invokedExpr, (left as ConstantExpression).Type); - } - if (right is MemberExpression) - { - var invokedExpr = Expression.Invoke(right, (right as LambdaExpression).Parameters.Cast()); - innerRight = Expression.Convert(invokedExpr, (left as MemberExpression).Type); - } - } - bool sequenceEqual = false; - if (leftIsLambda && rightIsLambda) - { - { - Type leftType = ((LambdaExpression)left).Type; - Type rightType = ((LambdaExpression)right).Type; - Type[] leftTypeGenericArguments = leftType.GetGenericArguments(); - Type[] rightTypeGenericArguments = rightType.GetGenericArguments(); - if (leftTypeGenericArguments.SequenceEqual(rightTypeGenericArguments)) - { - sequenceEqual = true; - if (leftTypeGenericArguments.Length == 2) - { - Type TOut = leftTypeGenericArguments[1]; - - if (expressionType == ExpressionType.AndAlso) - { - return PredicateBuilder.And(left as Expression>, right as Expression>); - } - if (expressionType == ExpressionType.OrElse) - { - return PredicateBuilder.Or(left as Expression>, right as Expression>); - } - - } - } - else - { - if (leftTypeGenericArguments.Length == 2) - { - //sequence not equal - could be Func && Func - if (leftTypeGenericArguments.First() == rightTypeGenericArguments.First()) - { - bool leftIsObject = leftTypeGenericArguments.ElementAt(1) == typeof(object); - bool rightIsObject = rightTypeGenericArguments.ElementAt(1) == typeof(object); - //if one is an object but not the other - if (leftIsObject ^ rightIsObject) - { - if (leftIsObject) - { - //left side is object - if (innerLeft == null) - { - parameters = new ParameterExpression[(left as LambdaExpression).Parameters.Count]; - (left as LambdaExpression).Parameters.CopyTo(parameters, 0); - innerLeft = Expression.Invoke(left, parameters); - } - unboxedLeft = Expression.Unbox(innerLeft, rightTypeGenericArguments.ElementAt(1)); - - //left is invoked and unboxed to right's TOut, right was not boxed - if (expressionType == ExpressionType.AndAlso) - { - return PredicateBuilder.And(right as Expression>, Expression.Lambda>(unboxedLeft, parameters) as Expression>); - } - if (expressionType == ExpressionType.OrElse) - { - return PredicateBuilder.And(right as Expression>, Expression.Lambda>(unboxedLeft, parameters) as Expression>); - } - } - else - { - //right side is object - if (innerRight == null) - { - parameters = new ParameterExpression[(right as LambdaExpression).Parameters.Count]; - (right as LambdaExpression).Parameters.CopyTo(parameters, 0); - innerRight = Expression.Invoke(right, parameters); - } - unboxedRight = Expression.Unbox(innerRight, leftTypeGenericArguments.ElementAt(1)); - - //right is invoked and unboxed to left's TOut, left was not boxed - if (expressionType == ExpressionType.AndAlso) - { - return PredicateBuilder.And(left as Expression>, Expression.Lambda>(unboxedRight, parameters) as Expression>); - } - if (expressionType == ExpressionType.OrElse) - { - return PredicateBuilder.And(left as Expression>, Expression.Lambda>(unboxedRight, parameters) as Expression>); - } - } - - } - } - } - } - } - } - - if (leftIsLambda && innerLeft == null) - { - //left is a lambda, but the right was an unhandled expression type - //!ConstantExpression, !MemberExpression - //make sure the left gets invoked - if (parameters == null) - { - parameters = new ParameterExpression[(left as LambdaExpression).Parameters.Count]; - (left as LambdaExpression).Parameters.CopyTo(parameters, 0); - } - innerLeft = Expression.Invoke(left, parameters); - } - if (rightIsLambda && innerRight == null) - { - //right is a lambda, but the left was an unhandled expression type - //!ConstantExpression, !MemberExpression - //make sure the right gets invoked - if (parameters == null) - { - parameters = new ParameterExpression[(right as LambdaExpression).Parameters.Count]; - (right as LambdaExpression).Parameters.CopyTo(parameters, 0); - } - innerRight = Expression.Invoke(right, parameters); - } - if (leftIsLambda && !rightIsLambda && innerLeft != null && !(innerLeft is UnaryExpression) && innerLeft.Type == typeof(object)) - { - //innerLeft is an invoke - unboxedLeft = Expression.Unbox(innerLeft, right.Type); - } - if (rightIsLambda && !leftIsLambda && innerRight != null && !(innerRight is UnaryExpression) && innerRight.Type == typeof(object)) - { - //innerRight is an invoke - unboxedRight = Expression.Unbox(innerRight, left.Type); - } - - BinaryExpression binaryExpression = null; - var finalLeft = unboxedLeft ?? innerLeft ?? left; - var finalRight = unboxedRight ?? innerRight ?? right; - switch (expressionType) - { - case ExpressionType.Equal: - binaryExpression = Expression.Equal(finalLeft, finalRight); - break; - case ExpressionType.NotEqual: - binaryExpression = Expression.NotEqual(finalLeft, finalRight); - break; - case ExpressionType.GreaterThan: - binaryExpression = Expression.GreaterThan(finalLeft, finalRight); - break; - case ExpressionType.LessThan: - binaryExpression = Expression.LessThan(finalLeft, finalRight); - break; - case ExpressionType.GreaterThanOrEqual: - binaryExpression = Expression.GreaterThanOrEqual(finalLeft, finalRight); - break; - case ExpressionType.LessThanOrEqual: - binaryExpression = Expression.LessThanOrEqual(finalLeft, finalRight); - break; - case ExpressionType.Modulo: - binaryExpression = Expression.Modulo(finalLeft, finalRight); - return (Expression.Lambda>(binaryExpression, parameters)); - case ExpressionType.AndAlso: - if ((leftIsLambda && rightIsLambda && sequenceEqual) || (!leftIsLambda && !rightIsLambda)) - { - return Expression.AndAlso(left, right); - } - else - { - return (Expression.Lambda>(Expression.AndAlso(finalLeft, finalRight), parameters)); - } - case ExpressionType.OrElse: - if (leftIsLambda && rightIsLambda && sequenceEqual || (!leftIsLambda && !rightIsLambda)) - { - return Expression.OrElse(left, right); - } - else - { - return (Expression.Lambda>(Expression.OrElse(finalLeft, finalRight), parameters)); - } - default: - return Expression.Equal(left, right); - } - if (leftIsLambda || rightIsLambda) - { - var body = Expression.Condition(Expression.TypeEqual(innerLeft, right.Type), binaryExpression, Expression.Constant(false)); - return Expression.Lambda>(body, parameters); - } - else - { - return binaryExpression; - } - - } - - Expression GenerateNotEqual(Expression left, Expression right) - { - return HandleDynamicNodeLambdas(ExpressionType.NotEqual, left, right); - } - - Expression GenerateGreaterThan(Expression left, Expression right) - { - if (left.Type == typeof(string)) - { - return Expression.GreaterThan( - GenerateStaticMethodCall("Compare", left, right), - Expression.Constant(0) - ); - } - return HandleDynamicNodeLambdas(ExpressionType.GreaterThan, left, right); - } - - Expression GenerateGreaterThanEqual(Expression left, Expression right) - { - if (left.Type == typeof(string)) - { - return Expression.GreaterThanOrEqual( - GenerateStaticMethodCall("Compare", left, right), - Expression.Constant(0) - ); - } - return HandleDynamicNodeLambdas(ExpressionType.GreaterThanOrEqual, left, right); - } - - Expression GenerateLessThan(Expression left, Expression right) - { - if (left.Type == typeof(string)) - { - return Expression.LessThan( - GenerateStaticMethodCall("Compare", left, right), - Expression.Constant(0) - ); - } - return HandleDynamicNodeLambdas(ExpressionType.LessThan, left, right); - } - - Expression GenerateLessThanEqual(Expression left, Expression right) - { - if (left.Type == typeof(string)) - { - return Expression.LessThanOrEqual( - GenerateStaticMethodCall("Compare", left, right), - Expression.Constant(0) - ); - } - return HandleDynamicNodeLambdas(ExpressionType.LessThanOrEqual, left, right); - } - - Expression GenerateAdd(Expression left, Expression right) - { - if (left.Type == typeof(string) && right.Type == typeof(string)) - { - return GenerateStaticMethodCall("Concat", left, right); - } - return Expression.Add(left, right); - } - - Expression GenerateSubtract(Expression left, Expression right) - { - return Expression.Subtract(left, right); - } - - Expression GenerateStringConcat(Expression left, Expression right) - { - return Expression.Call( - null, - typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }), - new[] { left, right }); - } - - MethodInfo GetStaticMethod(string methodName, Expression left, Expression right) - { - return left.Type.GetMethod(methodName, new[] { left.Type, right.Type }); - } - - Expression GenerateStaticMethodCall(string methodName, Expression left, Expression right) - { - return Expression.Call(null, GetStaticMethod(methodName, left, right), new[] { left, right }); - } - - void SetTextPos(int pos) - { - textPos = pos; - ch = textPos < textLen ? text[textPos] : '\0'; - } - - void NextChar() - { - if (textPos < textLen) textPos++; - ch = textPos < textLen ? text[textPos] : '\0'; - } - - void NextToken() - { - while (Char.IsWhiteSpace(ch)) NextChar(); - TokenId t; - int tokenPos = textPos; - switch (ch) - { - case '!': - NextChar(); - if (ch == '=') - { - NextChar(); - t = TokenId.ExclamationEqual; - } - else - { - t = TokenId.Exclamation; - } - break; - case '%': - NextChar(); - t = TokenId.Percent; - break; - case '&': - NextChar(); - if (ch == '&') - { - NextChar(); - t = TokenId.DoubleAmphersand; - } - else - { - t = TokenId.Amphersand; - } - break; - case '(': - NextChar(); - t = TokenId.OpenParen; - break; - case ')': - NextChar(); - t = TokenId.CloseParen; - break; - case '*': - NextChar(); - t = TokenId.Asterisk; - break; - case '+': - NextChar(); - t = TokenId.Plus; - break; - case ',': - NextChar(); - t = TokenId.Comma; - break; - case '-': - NextChar(); - t = TokenId.Minus; - break; - case '.': - NextChar(); - t = TokenId.Dot; - break; - case '/': - NextChar(); - t = TokenId.Slash; - break; - case ':': - NextChar(); - t = TokenId.Colon; - break; - case '<': - NextChar(); - if (ch == '=') - { - NextChar(); - t = TokenId.LessThanEqual; - } - else if (ch == '>') - { - NextChar(); - t = TokenId.LessGreater; - } - else - { - t = TokenId.LessThan; - } - break; - case '=': - NextChar(); - if (ch == '=') - { - NextChar(); - t = TokenId.DoubleEqual; - } - else - { - t = TokenId.Equal; - } - break; - case '>': - NextChar(); - if (ch == '=') - { - NextChar(); - t = TokenId.GreaterThanEqual; - } - else - { - t = TokenId.GreaterThan; - } - break; - case '?': - NextChar(); - t = TokenId.Question; - break; - case '[': - NextChar(); - t = TokenId.OpenBracket; - break; - case ']': - NextChar(); - t = TokenId.CloseBracket; - break; - case '|': - NextChar(); - if (ch == '|') - { - NextChar(); - t = TokenId.DoubleBar; - } - else - { - t = TokenId.Bar; - } - break; - case '"': - case '\'': - char quote = ch; - do - { - NextChar(); - while (textPos < textLen && ch != quote) NextChar(); - if (textPos == textLen) - throw ParseError(textPos, Res.UnterminatedStringLiteral); - NextChar(); - } while (ch == quote); - t = TokenId.StringLiteral; - break; - default: - if (Char.IsLetter(ch) || ch == '@' || ch == '_') - { - do - { - NextChar(); - } while (Char.IsLetterOrDigit(ch) || ch == '_'); - t = TokenId.Identifier; - break; - } - if (Char.IsDigit(ch)) - { - t = TokenId.IntegerLiteral; - do - { - NextChar(); - } while (Char.IsDigit(ch)); - if (ch == '.') - { - t = TokenId.RealLiteral; - NextChar(); - ValidateDigit(); - do - { - NextChar(); - } while (Char.IsDigit(ch)); - } - if (ch == 'E' || ch == 'e') - { - t = TokenId.RealLiteral; - NextChar(); - if (ch == '+' || ch == '-') NextChar(); - ValidateDigit(); - do - { - NextChar(); - } while (Char.IsDigit(ch)); - } - if (ch == 'F' || ch == 'f') NextChar(); - break; - } - if (textPos == textLen) - { - t = TokenId.End; - break; - } - throw ParseError(textPos, Res.InvalidCharacter, ch); - } - token.id = t; - token.text = text.Substring(tokenPos, textPos - tokenPos); - token.pos = tokenPos; - } - - bool TokenIdentifierIs(string id) - { - return token.id == TokenId.Identifier && String.Equals(id, token.text, StringComparison.OrdinalIgnoreCase); - } - - string GetIdentifier() - { - ValidateToken(TokenId.Identifier, Res.IdentifierExpected); - string id = token.text; - if (id.Length > 1 && id[0] == '@') id = id.Substring(1); - return id; - } - - void ValidateDigit() - { - if (!Char.IsDigit(ch)) throw ParseError(textPos, Res.DigitExpected); - } - - void ValidateToken(TokenId t, string errorMessage) - { - if (token.id != t) throw ParseError(errorMessage); - } - - void ValidateToken(TokenId t) - { - if (token.id != t) throw ParseError(Res.SyntaxError); - } - - Exception ParseError(string format, params object[] args) - { - return ParseError(token.pos, format, args); - } - - Exception ParseError(int pos, string format, params object[] args) - { - return new ParseException(string.Format(System.Globalization.CultureInfo.CurrentCulture, format, args), pos); - } - - static Dictionary CreateKeywords() - { - Dictionary d = new Dictionary(StringComparer.OrdinalIgnoreCase); - d.Add("true", trueLiteral); - d.Add("false", falseLiteral); - d.Add("null", nullLiteral); - d.Add(keywordIt, keywordIt); - d.Add(keywordIif, keywordIif); - d.Add(keywordNew, keywordNew); - foreach (Type type in predefinedTypes) d.Add(type.Name, type); - return d; } } + + } \ No newline at end of file diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/ParseException.cs b/src/umbraco.MacroEngines/RazorDynamicNode/ParseException.cs index 8bedc7b484..732f8fe733 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/ParseException.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/ParseException.cs @@ -1,23 +1,25 @@ namespace System.Linq.Dynamic { + + [Obsolete("This class has been superceded by Umbraco.Core.Dynamics.ParseException")] public sealed class ParseException : Exception { - int position; + private readonly Umbraco.Core.Dynamics.ParseException _inner; public ParseException(string message, int position) : base(message) { - this.position = position; + _inner = new Umbraco.Core.Dynamics.ParseException(message, position); } public int Position { - get { return position; } + get { return _inner.Position; } } public override string ToString() { - return string.Format(Res.ParseExceptionFormat, Message, position); + return _inner.ToString(); } } } \ No newline at end of file diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/Signature.cs b/src/umbraco.MacroEngines/RazorDynamicNode/Signature.cs index 99a6134205..408cff69bd 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/Signature.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/Signature.cs @@ -2,40 +2,11 @@ using System.Collections.Generic; namespace System.Linq.Dynamic { - internal class Signature : IEquatable + [Obsolete("This class has been superceded by Umbraco.Core.Dynamics.Signature")] + internal class Signature : Umbraco.Core.Dynamics.Signature { - public DynamicProperty[] properties; - public int hashCode; - - public Signature(IEnumerable properties) + public Signature(IEnumerable properties) : base(properties) { - this.properties = properties.ToArray(); - hashCode = 0; - foreach (DynamicProperty p in properties) - { - hashCode ^= p.Name.GetHashCode() ^ p.Type.GetHashCode(); - } - } - - public override int GetHashCode() - { - return hashCode; - } - - public override bool Equals(object obj) - { - return obj is Signature ? Equals((Signature)obj) : false; - } - - public bool Equals(Signature other) - { - if (properties.Length != other.properties.Length) return false; - for (int i = 0; i < properties.Length; i++) - { - if (properties[i].Name != other.properties[i].Name || - properties[i].Type != other.properties[i].Type) return false; - } - return true; } } } \ No newline at end of file