public static Expression BindMethodExpression(MethodCallExpression m, bool allowPolymorphics) { if (m.Method.DeclaringType == typeof(ExpressionExtensions) && m.Method.Name == "Evaluate") { LambdaExpression lambda = (LambdaExpression)(ExpressionEvaluator.Eval(m.Arguments[0])); return(Expression.Invoke(lambda, m.Arguments.Skip(1).ToArray())); } if (m.Method.HasAttributeInherit <PolymorphicExpansionAttribute>() && !allowPolymorphics) { return(null); } MethodExpanderAttribute attribute = m.Method.GetCustomAttribute <MethodExpanderAttribute>(); if (attribute != null) { if (attribute.ExpanderType.IsGenericTypeDefinition) { if (!typeof(GenericMethodExpander).IsAssignableFrom(attribute.ExpanderType)) { throw new InvalidOperationException("Expansion failed, '{0}' does not implement IMethodExpander or GenericMethodExpander".FormatWith(attribute.ExpanderType.TypeName())); } Expression[] args = m.Object == null?m.Arguments.ToArray() : m.Arguments.PreAnd(m.Object).ToArray(); var type = attribute.ExpanderType.MakeGenericType(m.Method.GetGenericArguments()); GenericMethodExpander expander = Activator.CreateInstance(type) as GenericMethodExpander; return(Expression.Invoke(expander.GenericLambdaExpression, args)); } else { if (!typeof(IMethodExpander).IsAssignableFrom(attribute.ExpanderType)) { throw new InvalidOperationException("Expansion failed, '{0}' does not implement IMethodExpander or GenericMethodExpander".FormatWith(attribute.ExpanderType.TypeName())); } IMethodExpander expander = (IMethodExpander)Activator.CreateInstance(attribute.ExpanderType); Expression exp = expander.Expand( m.Object, m.Arguments.ToArray(), m.Method); return(exp); } } LambdaExpression lambdaExpression = GetFieldExpansion(m.Object?.Type, m.Method); if (lambdaExpression != null) { Expression[] args = m.Object == null?m.Arguments.ToArray() : m.Arguments.PreAnd(m.Object).ToArray(); return(Expression.Invoke(lambdaExpression, args)); } return(null); }
internal override Expression VisitMethodCall(MethodCallExpression m) { // Expand expression tree 'calls' object[] attrs = m.Method.GetCustomAttributes(typeof(MethodExpanderAttribute), false); if (attrs.Length > 0) { MethodExpanderAttribute attr = (MethodExpanderAttribute)attrs[0]; IMethodExpander exp = Activator.CreateInstance(attr.ExpanderType) as IMethodExpander; if (exp == null) { throw new InvalidOperationException(string.Format( "LINQ method mapping expansion failed! Type '{0}' does not implement IMethodExpander interface.", attr.ExpanderType.Name)); } return(exp.Expand(Visit(m.Arguments[0]), m.Arguments.Skip(1).Select(p => Visit(p)))); } if (m.Method.DeclaringType == typeof(ExpressionExtensions)) { LambdaExpression lambda = (LambdaExpression)(Evaluate(m.Arguments[0])); Dictionary <ParameterExpression, Expression> replaceVars = new Dictionary <ParameterExpression, Expression>(); for (int i = 0; i < lambda.Parameters.Count; i++) { Expression rep = m.Arguments[i + 1]; if ((_replaceVars != null) && (rep is ParameterExpression) && (_replaceVars.ContainsKey((ParameterExpression)rep))) { replaceVars.Add(lambda.Parameters[i], _replaceVars[(ParameterExpression)rep]); } else { replaceVars.Add(lambda.Parameters[i], rep); } } if (_replaceVars != null) { foreach (KeyValuePair <ParameterExpression, Expression> pair in _replaceVars) { replaceVars.Add(pair.Key, pair.Value); } } return(new ExpressionExpander(replaceVars).Visit(lambda.Body)); } return(base.VisitMethodCall(m)); }