protected override Expression VisitMember(MemberExpression node) { PropertyInfo property = node.Member as PropertyInfo; MethodInfo getter; // We handle only properties (that aren't indexers) that have // a get if (property != null && property.GetIndexParameters().Length == 0 && (getter = property.GetGetMethod(true)) != null) { // We work only on methods marked as [ExpandableAttribute] var attribute = property.GetCustomAttribute(typeof(ExpandableAttribute)); if (attribute != null) { string name = property.Name + ExpandableAttribute.ExpandableSuffix; var property2 = property.DeclaringType.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, null, Type.EmptyTypes, null); if (property2 == null || property2.GetGetMethod(true) == null) { if (property2 == null) { if (property.DeclaringType.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, null, Type.EmptyTypes, null) != null) { throw new NotSupportedException(string.Format("{0}.{1} isn't static!", property.DeclaringType.FullName, name)); } throw new NotSupportedException(string.Format("{0}.{1} not found!", property.DeclaringType.FullName, name)); } // property2.GetGetMethod(true) == null throw new NotSupportedException(string.Format("{0}.{1} doesn't have a getter!", property.DeclaringType.FullName, name)); } // Instance Parameters have the additional // "parameter" of the declaring type var argumentsPlusReturnTypes = getter.IsStatic ? new[] { node.Type } : new[] { property.DeclaringType, node.Type }; var funcType = typeof(Func <>).Assembly.GetType(string.Format("System.Func`{0}", argumentsPlusReturnTypes.Length)); var returnType = typeof(Expression <>).MakeGenericType(funcType.MakeGenericType(argumentsPlusReturnTypes)); if (property2.PropertyType != returnType) { throw new NotSupportedException(string.Format("{0}.{1} has wrong return type!", property.DeclaringType.FullName, name)); } var expression = (LambdaExpression)property2.GetValue(null); // Instance Members have the additional "parameter" // of the declaring type var arguments2 = getter.IsStatic ? new Expression[0] : new[] { node.Expression }; var replacer = new ParametersReplacer(expression.Parameters, arguments2); var body = replacer.Visit(expression.Body); return(this.Visit(body)); } } return(base.VisitMember(node)); }
protected override Expression VisitMethodCall(MethodCallExpression node) { MethodInfo method = node.Method; // We work only on methods marked as [ExpandableAttribute] var attribute = method.GetCustomAttribute(typeof(ExpandableAttribute)); if (attribute != null) { string name = method.Name + ExpandableAttribute.ExpandableSuffix; var method2 = method.DeclaringType.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method2 == null) { if (method.DeclaringType.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null) != null) { throw new NotSupportedException(string.Format("{0}.{1} isn't static!", method.DeclaringType.FullName, name)); } throw new NotSupportedException(string.Format("{0}.{1} not found!", method.DeclaringType.FullName, name)); } // Instance methods have the additional "parameter" of // the declaring type var argumentsPlusReturnTypes = method.IsStatic ? node.Arguments.Select(x => x.Type).Concat(new[] { node.Type }).ToArray() : new[] { method.DeclaringType }.Concat(node.Arguments.Select(x => x.Type)).Concat(new[] { node.Type }).ToArray(); var funcType = typeof(Func <>).Assembly.GetType(string.Format("System.Func`{0}", argumentsPlusReturnTypes.Length)); var returnType = typeof(Expression <>).MakeGenericType(funcType.MakeGenericType(argumentsPlusReturnTypes)); if (method2.ReturnType != returnType) { throw new NotSupportedException(string.Format("{0}.{1} has wrong return type!", method.DeclaringType.FullName, name)); } var expression = (LambdaExpression)method2.Invoke(null, null); // Instance methods have the additional "parameter" of // the declaring type var arguments2 = method.IsStatic ? node.Arguments : new[] { node.Object }.Concat(node.Arguments); var replacer = new ParametersReplacer(expression.Parameters, arguments2); var body = replacer.Visit(expression.Body); return(this.Visit(body)); } return(base.VisitMethodCall(node)); }