diff --git a/IharBury.Expressions.sln b/IharBury.Expressions.sln index 321bbe5..3b925de 100644 --- a/IharBury.Expressions.sln +++ b/IharBury.Expressions.sln @@ -1,20 +1,17 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{17E67771-410B-4CCB-ABF7-30E89B868247}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CC2F5DE4-0070-486A-B269-DEE912BDA490}" - ProjectSection(SolutionItems) = preProject - global.json = global.json - EndProjectSection EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "IharBury.Expressions", "src\IharBury.Expressions\IharBury.Expressions.xproj", "{8A77AEDF-DF6A-4DB9-8499-DF0B89250E67}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2E635B3B-8AF5-475D-8E28-5BEE24E6663D}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "IharBury.Expressions.Tests", "test\IharBury.Expressions.Tests\IharBury.Expressions.Tests.xproj", "{43627114-3681-41BD-99EC-DCA4CBB68602}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IharBury.Expressions", "src\IharBury.Expressions\IharBury.Expressions.csproj", "{8A77AEDF-DF6A-4DB9-8499-DF0B89250E67}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2E635B3B-8AF5-475D-8E28-5BEE24E6663D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IharBury.Expressions.Tests", "test\IharBury.Expressions.Tests\IharBury.Expressions.Tests.csproj", "{43627114-3681-41BD-99EC-DCA4CBB68602}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/global.json b/global.json deleted file mode 100644 index a2b2a41..0000000 --- a/global.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "projects": [ "src", "test" ], - "sdk": { - "version": "1.0.0-preview2-003121" - } -} diff --git a/pack.cmd b/pack.cmd index ee1d302..1d3d299 100644 --- a/pack.cmd +++ b/pack.cmd @@ -1,7 +1,7 @@ @echo off -call test.cmd +call test.cmd Release pushd src\IharBury.Expressions -dotnet pack --configuration Release +dotnet pack --configuration Release --include-symbols popd \ No newline at end of file diff --git a/src/IharBury.Expressions/BooleanExpressions.cs b/src/IharBury.Expressions/BooleanExpressions.cs index ca3de8a..7abaf14 100644 --- a/src/IharBury.Expressions/BooleanExpressions.cs +++ b/src/IharBury.Expressions/BooleanExpressions.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; namespace IharBury.Expressions @@ -22,7 +21,7 @@ public static Expression> CombineViaAndAlso(IEnumerable>)Combine(expressions.CovariantCast(), Expression.AndAlso); + return (Expression>)Combine(expressions, Expression.AndAlso); } /// @@ -38,7 +37,7 @@ public static Expression> CombineViaAndAlso( if (expressions == null) throw new ArgumentNullException(nameof(expressions)); - return (Expression>)Combine(expressions.CovariantCast(), Expression.AndAlso); + return (Expression>)Combine(expressions, Expression.AndAlso); } /// @@ -54,7 +53,7 @@ public static Expression> CombineViaAndAlso( if (expressions == null) throw new ArgumentNullException(nameof(expressions)); - return (Expression>)Combine(expressions.CovariantCast(), Expression.AndAlso); + return (Expression>)Combine(expressions, Expression.AndAlso); } /// @@ -70,7 +69,7 @@ public static Expression> CombineViaAndAlso( if (expressions == null) throw new ArgumentNullException(nameof(expressions)); - return (Expression>)Combine(expressions.CovariantCast(), Expression.AndAlso); + return (Expression>)Combine(expressions, Expression.AndAlso); } /// @@ -86,10 +85,9 @@ public static Expression> CombineViaAndAlso>)Combine(expressions.CovariantCast(), Expression.AndAlso); + return (Expression>)Combine(expressions, Expression.AndAlso); } -#if !NET35 && !NET35_CLIENT /// /// Combines boolean expressions with same parameters via AndAlso /// (logical "and" that evaluates the second argument only when the first one is true). @@ -304,7 +302,6 @@ public static Expression /// Combines boolean expressions without parameters via OrElse @@ -318,7 +315,7 @@ public static Expression> CombineViaOrElse(IEnumerable>)Combine(expressions.CovariantCast(), Expression.OrElse); + return (Expression>)Combine(expressions, Expression.OrElse); } /// @@ -334,7 +331,7 @@ public static Expression> CombineViaOrElse( if (expressions == null) throw new ArgumentNullException(nameof(expressions)); - return (Expression>)Combine(expressions.CovariantCast(), Expression.OrElse); + return (Expression>)Combine(expressions, Expression.OrElse); } /// @@ -350,7 +347,7 @@ public static Expression> CombineViaOrElse( if (expressions == null) throw new ArgumentNullException(nameof(expressions)); - return (Expression>)Combine(expressions.CovariantCast(), Expression.OrElse); + return (Expression>)Combine(expressions, Expression.OrElse); } /// @@ -366,7 +363,7 @@ public static Expression> CombineViaOrElse( if (expressions == null) throw new ArgumentNullException(nameof(expressions)); - return (Expression>)Combine(expressions.CovariantCast(), Expression.OrElse); + return (Expression>)Combine(expressions, Expression.OrElse); } /// @@ -382,10 +379,9 @@ public static Expression> CombineViaOrElse>)Combine(expressions.CovariantCast(), Expression.OrElse); + return (Expression>)Combine(expressions, Expression.OrElse); } -#if !NET35 && !NET35_CLIENT /// /// Combines boolean expressions with same parameters via OrElse /// (logical "or" that evaluates the second argument only when the first one is false). @@ -598,7 +594,6 @@ public static Expression expressions, @@ -647,7 +642,7 @@ private static LambdaExpression Combine( } if (firstExpression == null) throw new ArgumentException("Expression list is empty.", nameof(expressions)); - return resultBody.CreateLambda(resultParameters); + return Expression.Lambda(resultBody, resultParameters); } } } diff --git a/src/IharBury.Expressions/CompatibilityExtensions.cs b/src/IharBury.Expressions/CompatibilityExtensions.cs deleted file mode 100644 index e7dfec8..0000000 --- a/src/IharBury.Expressions/CompatibilityExtensions.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; - -namespace IharBury.Expressions -{ - internal static class CompatibilityExtensions - { - public static Type GetBaseType(this Type type) - { - if (type == null) - throw new ArgumentNullException(nameof(type)); - -#if NET35 || NET35_CLIENT || NET40 || NET40_CLIENT - return type.BaseType; -#else - return type.GetTypeInfo().BaseType; -#endif - } - - public static IEnumerable GetDeclaredProperties(this Type type) - { - if (type == null) - throw new ArgumentNullException(nameof(type)); - -#if NET35 || NET35_CLIENT || NET40 || NET40_CLIENT - return type.GetProperties(BindingFlags.DeclaredOnly | - BindingFlags.Instance | - BindingFlags.Static | - BindingFlags.Public | - BindingFlags.NonPublic); -#else - return type.GetTypeInfo().DeclaredProperties; -#endif - } - - public static bool GetIsConstructedGenericType(this Type type) - { - if (type == null) - throw new ArgumentNullException(nameof(type)); - -#if NET35 || NET35_CLIENT || NET40 || NET40_CLIENT - return type.IsGenericType && !type.IsGenericTypeDefinition; -#else - return type.IsConstructedGenericType; -#endif - } - - public static MethodInfo FindMethod(this Type type, string name, params Type[] parameterTypes) - { - if (type == null) - throw new ArgumentNullException(nameof(type)); - if (string.IsNullOrEmpty(name)) - throw new ArgumentException($"string.{nameof(string.IsNullOrEmpty)}({nameof(name)}name)", nameof(name)); - if (parameterTypes == null) - throw new ArgumentNullException(nameof(parameterTypes)); - - return type -#if NET35 || NET35_CLIENT || NET40 || NET40_CLIENT - .GetMethods() - .Where(method => method.Name == name) -#else - .GetTypeInfo() - .GetDeclaredMethods(name) -#endif - .SingleOrDefault(method => - method.GetParameters().Select(parameter => parameter.ParameterType).SequenceEqual(parameterTypes)); - } - - public static MethodInfo GetGetMethod(this PropertyInfo property) - { - if (property == null) - throw new ArgumentNullException(nameof(property)); - -#if NET35 || NET35_CLIENT || NET40 || NET40_CLIENT - return property.GetGetMethod(); -#else - return property.GetMethod; -#endif - } - - public static IEnumerable CovariantCast(this IEnumerable> collection) - { - if (collection == null) - throw new ArgumentNullException(nameof(collection)); - -#if NET35 || NET35_CLIENT - return collection.Cast(); -#else - return collection; -#endif - } - - public static LambdaExpression CreateLambda(this Expression body, IEnumerable parameters) - { - if (body == null) - throw new ArgumentNullException(nameof(body)); - - return Expression.Lambda( - body, -#if NET35 || NET35_CLIENT - parameters.ToArray()); -#else - parameters); -#endif - } - - public static LambdaExpression Update( - this LambdaExpression expression, - Expression body, - IEnumerable parameters) - { - if (expression == null) - throw new ArgumentNullException(nameof(expression)); - -#if NET35 || NET35_CLIENT - return Expression.Lambda(expression.Type, body, parameters); -#else - return expression.Update(body, parameters); -#endif - } - } -} diff --git a/src/IharBury.Expressions/ExpressionExpander.cs b/src/IharBury.Expressions/ExpressionExpander.cs index 5a5477e..ca1a9d1 100644 --- a/src/IharBury.Expressions/ExpressionExpander.cs +++ b/src/IharBury.Expressions/ExpressionExpander.cs @@ -8,10 +8,26 @@ namespace IharBury.Expressions { internal sealed class ExpressionExpander : ExpressionVisitor { - private static readonly MethodInfo MethodInfoCreateDelegateMethod = typeof(MethodInfo) - .FindMethod("CreateDelegate", typeof(Type), typeof(object)); - private static readonly MethodInfo DelegateCreateDelegateMethod = typeof(Delegate) - .FindMethod("CreateDelegate", typeof(Type), typeof(object), typeof(MethodInfo)); + private static readonly MethodInfo MethodInfoCreateDelegateMethod = + FindMethod(typeof(MethodInfo), "CreateDelegate", typeof(Type), typeof(object)); + private static readonly MethodInfo DelegateCreateDelegateMethod = + FindMethod(typeof(Delegate), "CreateDelegate", typeof(Type), typeof(object), typeof(MethodInfo)); + + private static MethodInfo FindMethod(Type type, string name, params Type[] parameterTypes) + { + if (type == null) + throw new ArgumentNullException(nameof(type)); + if (string.IsNullOrEmpty(name)) + throw new ArgumentException($"string.{nameof(string.IsNullOrEmpty)}({nameof(name)}name)", nameof(name)); + if (parameterTypes == null) + throw new ArgumentNullException(nameof(parameterTypes)); + + return type + .GetTypeInfo() + .GetDeclaredMethods(name) + .SingleOrDefault(method => + method.GetParameters().Select(parameter => parameter.ParameterType).SequenceEqual(parameterTypes)); + } private ExpressionExpander() { } @@ -52,7 +68,7 @@ private static bool IsCompileMethod(MethodInfo method) throw new ArgumentNullException(nameof(method)); return (method.DeclaringType != null) && - method.DeclaringType.GetIsConstructedGenericType() && + method.DeclaringType.IsConstructedGenericType && (method.DeclaringType.GetGenericTypeDefinition() == typeof(Expression<>)) && (method.Name == nameof(Expression>.Compile)); } @@ -91,7 +107,7 @@ protected override Expression VisitMethodCall(MethodCallExpression node) } if ((baseResult.Method.DeclaringType != null) && - (baseResult.Method.DeclaringType.GetBaseType() == typeof(MulticastDelegate)) && + (baseResult.Method.DeclaringType.GetTypeInfo().BaseType == typeof(MulticastDelegate)) && (baseResult.Method.Name == nameof(Action.Invoke)) && (baseResult.Object != null) && (baseResult.Object.NodeType == ExpressionType.Call)) diff --git a/src/IharBury.Expressions/ExpressionParameterPresenceDetector.cs b/src/IharBury.Expressions/ExpressionParameterPresenceDetector.cs index 995f31f..3871d43 100644 --- a/src/IharBury.Expressions/ExpressionParameterPresenceDetector.cs +++ b/src/IharBury.Expressions/ExpressionParameterPresenceDetector.cs @@ -25,11 +25,7 @@ protected override Expression VisitParameter(ParameterExpression node) return base.VisitParameter(node); } -#if NET35 || NET35_CLIENT - protected override Expression VisitLambda(LambdaExpression node) -#else protected override Expression VisitLambda(Expression node) -#endif { allowedParameters.AddRange(node.Parameters); var result = base.VisitLambda(node); diff --git a/src/IharBury.Expressions/ExpressionParameterSubstitutor.cs b/src/IharBury.Expressions/ExpressionParameterSubstitutor.cs index 5560364..492a6b7 100644 --- a/src/IharBury.Expressions/ExpressionParameterSubstitutor.cs +++ b/src/IharBury.Expressions/ExpressionParameterSubstitutor.cs @@ -53,11 +53,7 @@ protected override Expression VisitParameter(ParameterExpression node) base.VisitParameter(node); } -#if NET35 || NET35_CLIENT - protected override Expression VisitLambda(LambdaExpression node) -#else protected override Expression VisitLambda(Expression node) -#endif { var newParameters = new List(node.Parameters.Count); diff --git a/src/IharBury.Expressions/ExpressionVisitor.cs b/src/IharBury.Expressions/ExpressionVisitor.cs deleted file mode 100644 index c522166..0000000 --- a/src/IharBury.Expressions/ExpressionVisitor.cs +++ /dev/null @@ -1,533 +0,0 @@ -#if NET35 || NET35_CLIENT -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Linq.Expressions; -using System.Text; - -namespace IharBury.Expressions -{ - /// - /// Represents a visitor or rewriter for expression trees. - /// Not present in .NET 4.0 and higher versions of the library - /// (use System.Linq.Expressions.ExpressionVisitor from System.Core.dll). - /// - /// - /// From MSDN: http://msdn.microsoft.com/en-us/library/bb882521(v=vs.90).aspx - /// - public abstract class ExpressionVisitor - { - /// - /// Dispatches the expression to one of the more specialized visit methods in this class. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression Visit(Expression exp) - { - if (exp == null) - return null; - - switch (exp.NodeType) - { - case ExpressionType.Negate: - case ExpressionType.NegateChecked: - case ExpressionType.Not: - case ExpressionType.Convert: - case ExpressionType.ConvertChecked: - case ExpressionType.ArrayLength: - case ExpressionType.Quote: - case ExpressionType.TypeAs: - return VisitUnary((UnaryExpression)exp); - - case ExpressionType.Add: - case ExpressionType.AddChecked: - case ExpressionType.Subtract: - case ExpressionType.SubtractChecked: - case ExpressionType.Multiply: - case ExpressionType.MultiplyChecked: - case ExpressionType.Divide: - case ExpressionType.Modulo: - case ExpressionType.And: - case ExpressionType.AndAlso: - case ExpressionType.Or: - case ExpressionType.OrElse: - case ExpressionType.LessThan: - case ExpressionType.LessThanOrEqual: - case ExpressionType.GreaterThan: - case ExpressionType.GreaterThanOrEqual: - case ExpressionType.Equal: - case ExpressionType.NotEqual: - case ExpressionType.Coalesce: - case ExpressionType.ArrayIndex: - case ExpressionType.RightShift: - case ExpressionType.LeftShift: - case ExpressionType.ExclusiveOr: - return VisitBinary((BinaryExpression)exp); - - case ExpressionType.TypeIs: - return VisitTypeIs((TypeBinaryExpression)exp); - - case ExpressionType.Conditional: - return VisitConditional((ConditionalExpression)exp); - - case ExpressionType.Constant: - return VisitConstant((ConstantExpression)exp); - - case ExpressionType.Parameter: - return VisitParameter((ParameterExpression)exp); - - case ExpressionType.MemberAccess: - return VisitMemberAccess((MemberExpression)exp); - - case ExpressionType.Call: - return VisitMethodCall((MethodCallExpression)exp); - - case ExpressionType.Lambda: - return VisitLambda((LambdaExpression)exp); - - case ExpressionType.New: - return VisitNew((NewExpression)exp); - - case ExpressionType.NewArrayInit: - case ExpressionType.NewArrayBounds: - return VisitNewArray((NewArrayExpression)exp); - - case ExpressionType.Invoke: - return VisitInvocation((InvocationExpression)exp); - - case ExpressionType.MemberInit: - return VisitMemberInit((MemberInitExpression)exp); - - case ExpressionType.ListInit: - return VisitListInit((ListInitExpression)exp); - - default: - throw new Exception(string.Format("Unhandled expression type: '{0}'", exp.NodeType)); - } - } - - /// - /// Visits the children of the MemberBinding. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual MemberBinding VisitBinding(MemberBinding binding) - { - if (binding == null) - throw new ArgumentNullException("binding"); - - switch (binding.BindingType) - { - case MemberBindingType.Assignment: - return VisitMemberAssignment((MemberAssignment)binding); - - case MemberBindingType.MemberBinding: - return VisitMemberMemberBinding((MemberMemberBinding)binding); - - case MemberBindingType.ListBinding: - return VisitMemberListBinding((MemberListBinding)binding); - - default: - throw new Exception(string.Format("Unhandled binding type '{0}'", binding.BindingType)); - } - } - - /// - /// Visits the children of the ElementInit. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual ElementInit VisitElementInitializer(ElementInit initializer) - { - if (initializer == null) - throw new ArgumentNullException("initializer"); - - var arguments = VisitExpressionList(initializer.Arguments); - return arguments == initializer.Arguments ? initializer : Expression.ElementInit(initializer.AddMethod, arguments); - } - - /// - /// Visits the children of the UnaryExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitUnary(UnaryExpression u) - { - if (u == null) - throw new ArgumentNullException("u"); - - var operand = Visit(u.Operand); - return operand == u.Operand ? u : Expression.MakeUnary(u.NodeType, operand, u.Type, u.Method); - } - - /// - /// Visits the children of the BinaryExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitBinary(BinaryExpression b) - { - if (b == null) - throw new ArgumentNullException("b"); - - var left = Visit(b.Left); - var right = Visit(b.Right); - var conversion = Visit(b.Conversion); - if (left == b.Left && right == b.Right && conversion == b.Conversion) - return b; - if (b.NodeType == ExpressionType.Coalesce && b.Conversion != null) - return Expression.Coalesce(left, right, conversion as LambdaExpression); - return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method); - } - - /// - /// Visits the children of the TypeBinaryExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitTypeIs(TypeBinaryExpression b) - { - if (b == null) - throw new ArgumentNullException("b"); - - var expr = Visit(b.Expression); - return expr == b.Expression ? b : Expression.TypeIs(expr, b.TypeOperand); - } - - /// - /// Visits the ConstantExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitConstant(ConstantExpression c) - { - if (c == null) - throw new ArgumentNullException("c"); - - return c; - } - - /// - /// Visits the children of the ConditionalExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitConditional(ConditionalExpression c) - { - if (c == null) - throw new ArgumentNullException("c"); - - var test = Visit(c.Test); - var ifTrue = Visit(c.IfTrue); - var ifFalse = Visit(c.IfFalse); - return test == c.Test && ifTrue == c.IfTrue && ifFalse == c.IfFalse ? c : Expression.Condition(test, ifTrue, ifFalse); - } - - /// - /// Visits the ParameterExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitParameter(ParameterExpression p) - { - if (p == null) - throw new ArgumentNullException("p"); - - return p; - } - - /// - /// Visits the children of the MemberExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitMemberAccess(MemberExpression m) - { - if (m == null) - throw new ArgumentNullException("m"); - - var exp = Visit(m.Expression); - return exp == m.Expression ? m : Expression.MakeMemberAccess(exp, m.Member); - } - - /// - /// Visits the children of the MethodCallExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitMethodCall(MethodCallExpression m) - { - if (m == null) - throw new ArgumentNullException("m"); - - var obj = Visit(m.Object); - var args = VisitExpressionList(m.Arguments); - return obj == m.Object && args == m.Arguments ? m : Expression.Call(obj, m.Method, args); - } - - /// - /// Dispatches the list of expressions to one of the more specialized visit methods in this class. - /// - /// The expressions to visit. - /// The modified expression list, if any one of the elements were modified; - /// otherwise, returns the original expression list. - protected virtual ReadOnlyCollection VisitExpressionList(ReadOnlyCollection original) - { - if (original == null) - throw new ArgumentNullException("original"); - - List list = null; - for (int i = 0, n = original.Count; i < n; i++) - { - var p = Visit(original[i]); - if (list != null) - { - list.Add(p); - } - else if (p != original[i]) - { - list = new List(n); - for (var j = 0; j < i; j++) - { - list.Add(original[j]); - } - list.Add(p); - } - } - return list == null ? original : new ReadOnlyCollection(list); - } - - /// - /// Visits the children of the MemberAssignment. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment) - { - if (assignment == null) - throw new ArgumentNullException("assignment"); - - var e = Visit(assignment.Expression); - return e == assignment.Expression ? assignment : Expression.Bind(assignment.Member, e); - } - - /// - /// Visits the children of the MemberMemberBinding. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) - { - if (binding == null) - throw new ArgumentNullException("binding"); - - var bindings = VisitBindingList(binding.Bindings); - return bindings == binding.Bindings ? binding : Expression.MemberBind(binding.Member, bindings); - } - - /// - /// Visits the children of the MemberListBinding. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding) - { - if (binding == null) - throw new ArgumentNullException("binding"); - - var initializers = VisitElementInitializerList(binding.Initializers); - return initializers == binding.Initializers ? binding : Expression.ListBind(binding.Member, initializers); - } - - /// - /// Visits all MemberBinding nodes in the collection using VisitBinding method. - /// - /// The nodes to visit. - /// The modified node list, if any of the elements were modified; - /// otherwise, returns the original node list. - protected virtual IEnumerable VisitBindingList(ReadOnlyCollection original) - { - if (original == null) - throw new ArgumentNullException("original"); - - List list = null; - for (int i = 0, n = original.Count; i < n; i++) - { - var b = VisitBinding(original[i]); - if (list != null) - { - list.Add(b); - } - else if (b != original[i]) - { - list = new List(n); - for (var j = 0; j < i; j++) - { - list.Add(original[j]); - } - list.Add(b); - } - } - if (list == null) - return original; - return list; - } - - /// - /// Visits all ElementInit nodes in the collection using VisitElementInitializer method. - /// - /// The nodes to visit. - /// The modified node list, if any of the elements were modified; - /// otherwise, returns the original node list. - protected virtual IEnumerable VisitElementInitializerList(ReadOnlyCollection original) - { - if (original == null) - throw new ArgumentNullException("original"); - - List list = null; - for (int i = 0, n = original.Count; i < n; i++) - { - var init = VisitElementInitializer(original[i]); - if (list != null) - { - list.Add(init); - } - else if (init != original[i]) - { - list = new List(n); - for (var j = 0; j < i; j++) - { - list.Add(original[j]); - } - list.Add(init); - } - } - if (list != null) - return list; - return original; - } - - /// - /// Visits the children of the LambdaExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitLambda(LambdaExpression lambda) - { - if (lambda == null) - throw new ArgumentNullException("lambda"); - - var body = Visit(lambda.Body); - return body == lambda.Body ? lambda : Expression.Lambda(lambda.Type, body, lambda.Parameters); - } - - /// - /// Visits the children of the NewExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual NewExpression VisitNew(NewExpression nex) - { - if (nex == null) - throw new ArgumentNullException("nex"); - - IEnumerable args = VisitExpressionList(nex.Arguments); - if (args == nex.Arguments) - return nex; - return nex.Members == null ? - Expression.New(nex.Constructor, args) : - Expression.New(nex.Constructor, args, nex.Members); - } - - /// - /// Visits the children of the MemberInitExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitMemberInit(MemberInitExpression init) - { - if (init == null) - throw new ArgumentNullException("init"); - - var n = VisitNew(init.NewExpression); - var bindings = VisitBindingList(init.Bindings); - if (n == init.NewExpression && bindings == init.Bindings) - return init; - return Expression.MemberInit(n, bindings); - } - - /// - /// Visits the children of the ListInitExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitListInit(ListInitExpression init) - { - if (init == null) - throw new ArgumentNullException("init"); - - var n = VisitNew(init.NewExpression); - var initializers = VisitElementInitializerList(init.Initializers); - if (n == init.NewExpression && initializers == init.Initializers) - return init; - return Expression.ListInit(n, initializers); - } - - /// - /// Visits the children of the NewArrayExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitNewArray(NewArrayExpression na) - { - if (na == null) - throw new ArgumentNullException("na"); - - var exprs = VisitExpressionList(na.Expressions); - if (exprs == na.Expressions) - return na; - if (na.NodeType == ExpressionType.NewArrayInit) - return Expression.NewArrayInit(na.Type.GetElementType(), exprs); - return Expression.NewArrayBounds(na.Type.GetElementType(), exprs); - } - - /// - /// Visits the children of the InvocationExpression. - /// - /// The expression to visit. - /// The modified expression, if it or any subexpression was modified; - /// otherwise, returns the original expression. - protected virtual Expression VisitInvocation(InvocationExpression iv) - { - if (iv == null) - throw new ArgumentNullException("iv"); - - var args = VisitExpressionList(iv.Arguments); - var expr = Visit(iv.Expression); - if (args == iv.Arguments && expr == iv.Expression) - return iv; - return Expression.Invoke(expr, args); - } - } -} -#endif diff --git a/src/IharBury.Expressions/Extensions.cs b/src/IharBury.Expressions/Extensions.cs index 36029a0..08be479 100644 --- a/src/IharBury.Expressions/Extensions.cs +++ b/src/IharBury.Expressions/Extensions.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Reflection; namespace IharBury.Expressions { @@ -183,7 +182,6 @@ public static TResult Evaluate( argument4); } -#if !NET35 && !NET35_CLIENT /// /// Represent expression evaluation. Intended to be used in another expression that is later transformed /// via ExpandExpressions method. @@ -891,7 +889,6 @@ public static TResult Evaluate /// Combines two boolean expressions without parameters via AndAlso @@ -1008,7 +1005,6 @@ public static Expression> AndAlso( }); } -#if !NET35 && !NET35_CLIENT /// /// Combines two boolean expressions with same parameters via AndAlso /// (logical "and" that evaluates the second argument only when the first one is true). @@ -1293,7 +1289,6 @@ public static Expression /// Combines two boolean expressions without parameters via OrElse @@ -1410,7 +1405,6 @@ public static Expression> OrElse( }); } -#if !NET35 && !NET35_CLIENT /// /// Combines two boolean expressions with same parameters via OrElse /// (logical "or" that evaluates the second argument only when the first one is false). @@ -1695,7 +1689,6 @@ public static Expression /// Returns default value of compile-time type of the element of the given enumerable. diff --git a/src/IharBury.Expressions/IharBury.Expressions.csproj b/src/IharBury.Expressions/IharBury.Expressions.csproj new file mode 100644 index 0000000..a84e436 --- /dev/null +++ b/src/IharBury.Expressions/IharBury.Expressions.csproj @@ -0,0 +1,15 @@ + + + + Allows to include lambda expressions into each other in c# and Visual Basic. Also allows to avoid using string constants in reflection thus enabling easy refactoring. + 1.2.0 + Ihar Bury + netstandard1.0 + IharBury.Expressions + IharBury.Expressions + expressions;linq;lambda;reflection;iqueryable;entityframework;ef;nhibernate + https://github.com/IharBury/expressions/wiki + http://opensource.org/licenses/mit-license.php + + + diff --git a/src/IharBury.Expressions/IharBury.Expressions.xproj b/src/IharBury.Expressions/IharBury.Expressions.xproj deleted file mode 100644 index d4fe5a0..0000000 --- a/src/IharBury.Expressions/IharBury.Expressions.xproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 8a77aedf-df6a-4db9-8499-df0b89250e67 - IharBury.Expressions - .\obj - .\bin\ - v4.6 - - - 2.0 - - - \ No newline at end of file diff --git a/src/IharBury.Expressions/Lambda.cs b/src/IharBury.Expressions/Lambda.cs index cc29bf2..4d84229 100644 --- a/src/IharBury.Expressions/Lambda.cs +++ b/src/IharBury.Expressions/Lambda.cs @@ -112,7 +112,6 @@ public static Expression> Expression /// Returns lambda as expression. /// @@ -697,7 +696,6 @@ public static Expression> Expression /// Returns lambda as delegate. @@ -803,7 +801,6 @@ public static Func Func( return lambda; } -#if !NET35 && !NET35_CLIENT /// /// Returns lambda as delegate. /// @@ -1382,6 +1379,5 @@ public static Func Func property.GetGetMethod() == methodCallExpression.Method); + .GetTypeInfo() + .DeclaredProperties + .SingleOrDefault(property => property.GetMethod == methodCallExpression.Method); return null; default: diff --git a/src/IharBury.Expressions/project.json b/src/IharBury.Expressions/project.json deleted file mode 100644 index a89b3eb..0000000 --- a/src/IharBury.Expressions/project.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": "1.1.4", - "description": "Allows to include lambda expressions into each other in c# and Visual Basic. Also allows to avoid using string constants in reflection thus enabling easy refactoring.", - "authors": [ "Ihar Bury" ], - "packOptions": { - "tags": [ "expressions", "linq", "lambda", "reflection", "iqueryable", "entityframework", "ef", "nhibernate" ], - "projectUrl": "https://github.com/IharBury/expressions/wiki", - "licenseUrl": "http://opensource.org/licenses/mit-license.php" - }, - "frameworks": { - "netstandard1.0": { - "dependencies": { - "System.Collections": "4.0.11", - "System.Linq": "4.1.0", - "System.Linq.Expressions": "4.1.0", - "System.Runtime": "4.1.0", - "System.Reflection": "4.1.0" - } - }, - "net4.0": { }, - "net3.5": { }, - "net4.0-client": { }, - "net3.5-client": { } - } -} diff --git a/test.cmd b/test.cmd index c67f376..3ed0ca7 100644 --- a/test.cmd +++ b/test.cmd @@ -3,13 +3,9 @@ set configuration=%1 if "%1"=="" set configuration=Debug -%USERPROFILE%\.nuget\packages\xunit.runner.console\2.1.0\tools\xunit.console.exe test\IharBury.Expressions.Tests\bin\%configuration%\net46\win7-x64\IharBury.Expressions.Tests.dll -%USERPROFILE%\.nuget\packages\xunit.runner.console\2.1.0\tools\xunit.console.exe test\IharBury.Expressions.Tests\bin\%configuration%\net45\win7-x64\IharBury.Expressions.Tests.dll -%USERPROFILE%\.nuget\packages\xunit.runner.console\2.1.0\tools\xunit.console.exe test\IharBury.Expressions.Tests\bin\%configuration%\net40\win7-x64\IharBury.Expressions.Tests.dll -%USERPROFILE%\.nuget\packages\xunit.runner.console\2.1.0\tools\xunit.console.exe test\IharBury.Expressions.Tests\bin\%configuration%\net40-client\win7-x64\IharBury.Expressions.Tests.dll -%USERPROFILE%\.nuget\packages\xunit.runner.console\2.1.0\tools\xunit.console.exe test\IharBury.Expressions.Tests\bin\%configuration%\net35\win7-x64\IharBury.Expressions.Tests.dll -%USERPROFILE%\.nuget\packages\xunit.runner.console\2.1.0\tools\xunit.console.exe test\IharBury.Expressions.Tests\bin\%configuration%\net35-client\win7-x64\IharBury.Expressions.Tests.dll +%USERPROFILE%\.nuget\packages\xunit.runner.console\2.2.0\tools\xunit.console.exe test\IharBury.Expressions.Tests\bin\%configuration%\net462\IharBury.Expressions.Tests.dll +%USERPROFILE%\.nuget\packages\xunit.runner.console\2.2.0\tools\xunit.console.exe test\IharBury.Expressions.Tests\bin\%configuration%\net45\IharBury.Expressions.Tests.dll pushd test\IharBury.Expressions.Tests -dotnet test --runtime netcoreapp1.0 --framework netcoreapp1.0 --configuration %configuration% +dotnet test --framework netcoreapp1.0 --configuration %configuration% popd \ No newline at end of file diff --git a/test/IharBury.Expressions.Tests/BooleanExpressionsTests.cs b/test/IharBury.Expressions.Tests/BooleanExpressionsTests.cs index 2649820..f144b96 100644 --- a/test/IharBury.Expressions.Tests/BooleanExpressionsTests.cs +++ b/test/IharBury.Expressions.Tests/BooleanExpressionsTests.cs @@ -116,7 +116,6 @@ public void AndAlso4ParameterTest() } } -#if !NET35 && !NET35_CLIENT [Fact] public void AndAlso5ParameterTest() { @@ -392,7 +391,6 @@ public void AndAlso16ParameterTest() } } } -#endif [Fact] public void AndAlso2ParameterReplacementTest() @@ -526,7 +524,6 @@ public void OrElse4ParameterTest() } } -#if !NET35 && !NET35_CLIENT [Fact] public void OrElse5ParameterTest() { @@ -802,7 +799,6 @@ public void OrElse16ParameterTest() } } } -#endif [Fact] public void OrElse2ParameterReplacementTest() diff --git a/test/IharBury.Expressions.Tests/CompatibilityExtensions.cs b/test/IharBury.Expressions.Tests/CompatibilityExtensions.cs deleted file mode 100644 index 930f6b6..0000000 --- a/test/IharBury.Expressions.Tests/CompatibilityExtensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace IharBury.Expressions.Tests -{ - internal static class CompatibilityExtensions - { - internal static Type GetBaseType(this Type type) - { - if (type == null) - throw new ArgumentNullException(nameof(type)); - -#if NET35 || NET35_CLIENT || NET40 || NET40_CLIENT - return type.BaseType; -#else - return type.GetTypeInfo().BaseType; -#endif - } - - internal static IEnumerable GetDeclaredProperties(this Type type) - { - if (type == null) - throw new ArgumentNullException(nameof(type)); - -#if NET35 || NET35_CLIENT || NET40 || NET40_CLIENT - return type.GetProperties(BindingFlags.DeclaredOnly | - BindingFlags.Instance | - BindingFlags.Static | - BindingFlags.Public | - BindingFlags.NonPublic); -#else - return type.GetTypeInfo().DeclaredProperties; -#endif - } - - internal static bool GetIsConstructedGenericType(this Type type) - { - if (type == null) - throw new ArgumentNullException(nameof(type)); - -#if NET35 || NET35_CLIENT || NET40 || NET40_CLIENT - return type.IsGenericType && !type.IsGenericTypeDefinition; -#else - return type.IsConstructedGenericType; -#endif - } - } -} diff --git a/test/IharBury.Expressions.Tests/EvaluateTests.cs b/test/IharBury.Expressions.Tests/EvaluateTests.cs index 6812207..f1f5ccd 100644 --- a/test/IharBury.Expressions.Tests/EvaluateTests.cs +++ b/test/IharBury.Expressions.Tests/EvaluateTests.cs @@ -46,7 +46,6 @@ public void Evaluate4ArgumentsTest() Assert.Equal(30, f1.Evaluate(1, 2, 3, 4)); } -#if !NET35 && !NET35_CLIENT [Fact] public void Evaluate5ArgumentsTest() { @@ -159,6 +158,5 @@ public void Evaluate16ArgumentsTest() Assert.Equal(40, f1.Evaluate(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)); } -#endif } } diff --git a/test/IharBury.Expressions.Tests/ExpandExpressionTests.cs b/test/IharBury.Expressions.Tests/ExpandExpressionTests.cs index a0a9977..39d0b18 100644 --- a/test/IharBury.Expressions.Tests/ExpandExpressionTests.cs +++ b/test/IharBury.Expressions.Tests/ExpandExpressionTests.cs @@ -475,7 +475,7 @@ protected override Expression VisitInvocation(InvocationExpression node) var methodCallExpression = (MethodCallExpression)node.Expression; Assert.False( (methodCallExpression.Method.DeclaringType != null) && - methodCallExpression.Method.DeclaringType.GetIsConstructedGenericType() && + methodCallExpression.Method.DeclaringType.IsConstructedGenericType && (methodCallExpression.Method.DeclaringType.GetGenericTypeDefinition() == typeof(Expression<>)) && (methodCallExpression.Method.Name == CompileMethodName), $"The expression body has evaluation: \"{node}\"."); @@ -506,7 +506,7 @@ private static void ValidateMethod(Expression node, MethodInfo method) $"The expression body has evaluation: \"{node}\"."); Assert.False( (method.DeclaringType != null) && - (method.DeclaringType.GetBaseType() == typeof(MulticastDelegate)) && + (method.DeclaringType.GetTypeInfo().BaseType == typeof(MulticastDelegate)) && (method.Name == ReflectionExpressions.GetMethodName(action => action.Invoke())), $"The expression body has invokation: \"{node}\"."); } @@ -539,11 +539,7 @@ public static void AssertNoDuplicateParameters(Expression expression) new NoDuplicateParameterAssertion().Visit(expression); } -#if NET35 || NET35_CLIENT - protected override Expression VisitLambda(LambdaExpression node) -#else protected override Expression VisitLambda(Expression node) -#endif { foreach (var parameter in node.Parameters) { diff --git a/test/IharBury.Expressions.Tests/IharBury.Expressions.Tests.csproj b/test/IharBury.Expressions.Tests/IharBury.Expressions.Tests.csproj new file mode 100644 index 0000000..fb210ba --- /dev/null +++ b/test/IharBury.Expressions.Tests/IharBury.Expressions.Tests.csproj @@ -0,0 +1,25 @@ + + + + Unit tests for IharBury.Expressions + 1.2.0 + Ihar Bury + netcoreapp1.0;net462;net45 + IharBury.Expressions.Tests + IharBury.Expressions.Tests + true + expressions;linq;lambda;reflection;iqueryable;entityframework;ef;nhibernate + https://github.com/IharBury/expressions/wiki + http://opensource.org/licenses/mit-license.php + + + + + + + + + + + + diff --git a/test/IharBury.Expressions.Tests/IharBury.Expressions.Tests.xproj b/test/IharBury.Expressions.Tests/IharBury.Expressions.Tests.xproj deleted file mode 100644 index f45345d..0000000 --- a/test/IharBury.Expressions.Tests/IharBury.Expressions.Tests.xproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 43627114-3681-41bd-99ec-dca4cbb68602 - IharBury.Expressions.Tests - .\obj - .\bin\ - v4.6 - - - 2.0 - - - - - - \ No newline at end of file diff --git a/test/IharBury.Expressions.Tests/LambdaExpressionTests.cs b/test/IharBury.Expressions.Tests/LambdaExpressionTests.cs index 3b9baf4..9e3d4d2 100644 --- a/test/IharBury.Expressions.Tests/LambdaExpressionTests.cs +++ b/test/IharBury.Expressions.Tests/LambdaExpressionTests.cs @@ -118,7 +118,6 @@ public void ExpressionWith4ParametersLambda() expression.Compile().Invoke(argument1Example, argument2Example, argument3Example, argument4Example); } -#if !NET35 && !NET35_CLIENT [Fact] public void ExpressionWith5ParametersLambda() { @@ -1082,7 +1081,6 @@ public void ExpressionWith16ParametersLambda() argument15Example, argument16Example); } -#endif [Fact] public void FuncWith0ParametersLambda() @@ -1178,7 +1176,6 @@ public void FuncWith4ParametersLambda() lambdaDelegate(argument1Example, argument2Example, argument3Example, argument4Example); } -#if !NET35 && !NET35_CLIENT [Fact] public void FuncWith5ParametersLambda() { @@ -2142,6 +2139,5 @@ public void FuncWith16ParametersLambda() argument15Example, argument16Example); } -#endif } } diff --git a/test/IharBury.Expressions.Tests/project.json b/test/IharBury.Expressions.Tests/project.json deleted file mode 100644 index 4a31953..0000000 --- a/test/IharBury.Expressions.Tests/project.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "version": "1.1.4", - "description": "Unit tests for IharBury.Expressions", - "authors": [ "Ihar Bury" ], - "packOptions": { - "tags": [ "expressions", "linq", "lambda", "reflection", "iqueryable", "entityframework", "ef", "nhibernate" ], - "projectUrl": "https://github.com/IharBury/expressions/wiki", - "licenseUrl": "http://opensource.org/licenses/mit-license.php" - }, - "dependencies": { - "IharBury.Expressions": "1.1.4" - }, - "testRunner": "xunit", - "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.0" - }, - "xunit": "2.2.0-beta2-build3300", - "dotnet-test-xunit": "2.2.0-preview2-build1029" - } - }, - "net4.6": { - "dependencies": { - "xunit": "2.2.0-beta2-build3300", - "xunit.runner.console": "2.2.0-beta2-build3300", - "System.Runtime": "4.0.20" - } - }, - "net4.5": { - "dependencies": { - "xunit": "2.2.0-beta2-build3300", - "xunit.runner.console": "2.2.0-beta2-build3300", - "System.Runtime": "4.0.0" - } - }, - "net4.0": { - "dependencies": { - "xunit": "1.9.2", - "xunit.runner.console": "2.2.0-beta2-build3300" - } - }, - "net3.5": { - "dependencies": { - "xunit": "1.9.2", - "xunit.runner.console": "2.2.0-beta2-build3300" - } - }, - "net4.0-client": { - "dependencies": { - "xunit": "1.9.2", - "xunit.runner.console": "2.2.0-beta2-build3300" - } - }, - "net3.5-client": { - "dependencies": { - "xunit": "1.9.2", - "xunit.runner.console": "2.2.0-beta2-build3300" - } - } - } -}