/// <summary> /// 通过实体类型获取实体信息 /// </summary> /// <param name="type"></param> /// <returns></returns> public EntityInfo GetEntity(Type type) { EntityInfo entityInfo = null; if (!_entityInfos.TryGetValue(type, out entityInfo)) { lock (_entityLocker) { entityInfo = new EntityInfo(); entityInfo.TableName = ExpressionUtil.GetEntityTableName(type); if (string.IsNullOrWhiteSpace(entityInfo.TableName)) { throw new Exception("实体必须标明TableAttribute"); } entityInfo.EntityType = type; var pis = ExpressionReflector.GetProperties(type).Values; foreach (var property in pis) { var foreignKeyAttr = AttributeHelper.GetAttribute <ForeignKeyAttribute>(property); if (foreignKeyAttr != null) { entityInfo.ForeignKeys.Add(property); } entityInfo.Properties.Add(property); } _entityInfos.Add(type, entityInfo); } } return(entityInfo); }
protected override Expression VisitLambda <T>(Expression <T> node) { if (node.Body is NewExpression) { //此处一般是在Select方法中new了匿名对象,例如users.Select(x=>new {x.Id}) return(base.VisitLambda <T>(node)); } //此处一般是在Select方法中直接选择了参数,例如users.Select(x=>x),这种情况下直接把x的所有列转换出来 var properties = ExpressionReflector.GetProperties(node.Body.Type).Values; foreach (var item in properties) { if (!ExpressionUtil.IsEntityPropertyType(item.PropertyType)) { continue; ////是否.Net自带的String、DateTime,如果不是则跳过 //if (!((item.PropertyType.FullName == "System.String" || item.PropertyType.FullName == "System.DateTime") && item.PropertyType.Assembly.GlobalAssemblyCache)) //{ // continue; //} ////是否可空,如果不是则跳过 //var type = Nullable.GetUnderlyingType(item.PropertyType); //if (type == null) //{ // continue; //} } _columnInfos.Add(item.Name, new KeyValuePair <string, string>(_masterTableName, item.Name)); } return(node); }
/// <summary> /// 从指定的参数列表中查找对应的name的表达式的父表达式 /// </summary> /// <param name="args"></param> /// <param name="name"></param> /// <returns>可能是MemberExpression和ParameterExpression</returns> Expression FindArgument(IEnumerable <Expression> args, MemberInfo memberInfo) { string name = memberInfo.Name; Type type = ExpressionUtil.GetMemberType(memberInfo); MemberExpression temp = null; foreach (Expression _arg in args) { //Expression target = null; if (_arg is ParameterExpression) { throw new Exception("Select子句中的匿名类不允许存在直接使用参数的表达式,例如x=>new {x}"); } var arg = (MemberExpression)_arg; if (arg.Member.Name == name && ExpressionUtil.GetMemberType(arg.Member) == type) { return(arg.Expression); } temp = (MemberExpression)arg.Expression; while (true) { if (temp.Expression is ParameterExpression) { break; } temp = (MemberExpression)temp.Expression; if (temp.Member.Name == name && ExpressionUtil.GetMemberType(temp.Member) == type) { return(temp.Expression); } } } return(null); }
protected override Expression VisitMember(MemberExpression node) { if (node.Expression is ParameterExpression) { //访问到了根节点了 if (_properties.Count <= 0) { _columnInfos.Add(node.Member.Name, new KeyValuePair <string, string>(_masterTableName, node.Member.Name)); } else { Type type = node.Type; if (type.IsGenericType) { type = Nullable.GetUnderlyingType(type); } if (!(type.FullName == "System.DateTime" && type.Assembly.GlobalAssemblyCache)) { throw new ArgumentException("Select子句中多个属性访问的表达式时,若属性名为Date,则只能支持访问DateTime类型的实体,例如x.Time.Date"); } NeedWrapSelect = true; _columnInfos.Add(node.Member.Name, new KeyValuePair <string, string>(_masterTableName, node.Member.Name)); _columnMethods.Add(new KeyValuePair <string, string>(_masterTableName, node.Member.Name), "CONVERT(NVARCHAR(20),{0},101)"); if (!_tableInfos.ContainsKey(_masterTableName)) { _tableInfos.Add(_masterTableName, ExpressionUtil.GenerateRandomTableAlias()); } _properties.Clear(); } } else { //不是根节点,取出Member属性用于计算值 PropertyInfo propertyInfo = (PropertyInfo)node.Member; if (propertyInfo.Name == "Value") { propertyInfo = (PropertyInfo)((MemberExpression)node.Expression).Member; //跳过可空类型 if (!propertyInfo.PropertyType.IsGenericType) { throw new ArgumentException("在Select子句中,若使用了多个属性访问的表达式并且属性名为Value,则该表达式只允许为访问Nullable<T>的表达式,例如如果实体的Time为DateTime?,则可以写为x.Time.Value"); } else { return(base.VisitMember(node)); } } NeedWrapSelect = true; _properties.Push(propertyInfo); } return(base.VisitMember(node)); }
protected override Expression VisitNew(NewExpression node) { //此处一般是在Select方法中new了匿名对象,例如users.Select(x=>new {x.Id}) foreach (System.Reflection.MemberInfo memberInfo in node.Members) { //检查当前成员的类型是否是实体类型,例如x=>new {x.User.Book.Id} //这种情况一般是外键访问,需要考虑与主表之间的关系 if (ExpressionUtil.IsEntityMember(memberInfo)) { //当前成员的类型是一个实体类型,需要考虑与主表的关系 var type = ExpressionUtil.GetMemberType(memberInfo); var entityInfo = _entityManager.GetEntity(type); var parentExpression = FindArgument(node.Arguments, memberInfo); if (parentExpression is ParameterExpression) { //该成员由参数直接调用,可直接考虑与主表的关系 } string tableName = entityInfo.TableName; //if (string.IsNullOrWhiteSpace(tableName)) //{ // throw new Exception("Select子句中选择的类型没有标TableAttribute特性或者特性中指定了空表名"); //} var pis = entityInfo.Properties; //_alias.AddRange(pis.Select(x => x.Name)); foreach (var propertyInfo in pis) { _columnInfos.Add(propertyInfo.Name, new KeyValuePair <string, string>(tableName, propertyInfo.Name)); } if (!_tableInfos.ContainsKey(tableName)) { _tableInfos.Add(tableName, ExpressionUtil.GenerateRandomTableAlias()); } } else { _columnInfos.Add(memberInfo.Name, new KeyValuePair <string, string>(_masterTableName, memberInfo.Name)); } } return(node); }
protected override Expression VisitMember(MemberExpression node) { if (node.Expression is ParameterExpression) { //到达根节点,并且一定是左枝 if (ExpressionUtil.IsEntityMember(node.Member)) { //x.User.Book.Id string tableName = ExpressionUtil.GetEntityTableName(ExpressionUtil.GetMemberType(node.Member)); if (string.IsNullOrWhiteSpace(tableName)) { throw new Exception("解析出错"); } string alia = _aliaTableNameMap[tableName]; field = _memberStack.Pop().Name; _conditionStack.Push("[" + alia + "].[" + field + "]"); _conditionStack.Push("@" + field); } else { //按照属性处理 field = node.Member.Name; if (_memberStack.Count > 0) { //有属性要转换为sql语句 var propertyInfo = (PropertyInfo)_memberStack.Pop(); if (propertyInfo.PropertyType.FullName == "System.DateTime" && propertyInfo.PropertyType.Assembly.GlobalAssemblyCache) { //该属性为日期时间型,可进行转换 _conditionStack.Push("CONVERT(NVARCHAR(20),[" + field + "],101)"); } else { throw new NotImplementedException("不允许使用当前属性取值:" + propertyInfo.PropertyType.Name + "," + propertyInfo.Name); } } else if (_memberStack.Count > 0) { //有方法要转换为sql语句 var method = _memberStack.Pop(); if (method.Name == "ToDateTime" && method.DeclaringType.Assembly.GlobalAssemblyCache) { _conditionStack.Push("CONVERT(NVARCHAR(20),[" + field + "],101)"); } else { throw new NotSupportedException("不支持指定方法的转换:" + method.Name); } } else { _conditionStack.Push("[" + field + "]"); } _conditionStack.Push("@" + field); } } else if (node.Expression == null) { //一定是静态成员,例如:x=>DateTime.Now中的Now,直接取出值 object value = null; if (node.Member.MemberType == MemberTypes.Field) { var fieldInfo = node.Member as FieldInfo; value = fieldInfo.GetValue(null); } else { var propertyInfo = node.Member as PropertyInfo; value = propertyInfo.GetValue(null, null); } while (_memberStack.Count > 0) { var member = _memberStack.Pop(); if (member.MemberType == MemberTypes.Field) { value = ((FieldInfo)member).GetValue(value); } else if (member.MemberType == MemberTypes.Property) { value = ((PropertyInfo)member).GetValue(value, null); } else { throw new NotSupportedException("未知的成员类型:" + member.MemberType); } } //if (node.Member.MemberType == MemberTypes.Field) //{ // var fieldInfo = node.Member as FieldInfo; // _list.Add(fieldInfo.GetValue(null)); //} //else //{ // var propertyInfo = node.Member as PropertyInfo; // _list.Add(propertyInfo.GetValue(null, null)); //} _list.Add(_conditionStack.Peek(), value); } else if (node.Expression is ConstantExpression) { //引用的局部变量 //var constExp = node.Expression as ConstantExpression; //var field = constExp.Value.GetType().GetField(node.Member.Name); //var rootValue = field.GetValue(constExp.Value); //while (_propertyStack.Count > 0) //{ // var property = _propertyStack.Pop(); // rootValue = property.GetValue(rootValue, null); //} //_paramStack.Push(rootValue); ObjectValueExpressionVisitor visitor = new ObjectValueExpressionVisitor(); visitor.Visit(node); if (visitor.Value is Array || visitor.Value is IEnumerable) { var rootValue = visitor.Value; var list = rootValue as IList; object result = rootValue; while (_memberStack.Count > 0) { var memberInfo = _memberStack.Pop(); if (memberInfo.MemberType == MemberTypes.Method) { var method = memberInfo as MethodInfo; IEnumerable <object> args = null; //if (method.Arguments[0] is ConstantExpression) //{ // args = mce.Arguments.Select(x => ((ConstantExpression)x).Value); // result = mce.Method.Invoke(rootValue, args.ToArray()); //} //else //{ // visitor = new ObjectValueExpressionVisitor(); // visitor.Visit(mce.Arguments[0]); // var extensionArgs = mce.Arguments.Skip(1).Select(x => ((ConstantExpression)x).Value).ToList(); // extensionArgs.Insert(0, visitor.Value); // result = mce.Method.Invoke(null, extensionArgs.ToArray()); //} } } if (_memberStack.Count > 0) { //MethodCallExpression mce = _memberStack.Pop(); //IEnumerable<object> args = null; //if (mce.Arguments[0] is ConstantExpression) //{ // args = mce.Arguments.Select(x => ((ConstantExpression)x).Value); // result = mce.Method.Invoke(rootValue, args.ToArray()); //} //else //{ // visitor = new ObjectValueExpressionVisitor(); // visitor.Visit(mce.Arguments[0]); // var extensionArgs = mce.Arguments.Skip(1).Select(x => ((ConstantExpression)x).Value).ToList(); // extensionArgs.Insert(0, visitor.Value); // result = mce.Method.Invoke(null, extensionArgs.ToArray()); //} } _list.Add(_conditionStack.Peek(), result); //_constStack.Push(rootValue); } else { _constStack.Push(visitor.Value); } _paramNameStack.Push(node.Member.Name); } else if (node.Expression is MemberExpression) { if (!ExpressionReflector.IsEntityPropertyType(ExpressionUtil.GetMemberType(((MemberExpression)node.Expression).Member))) { //x=>x.User.Book.Id _memberStack.Push(node.Member); } else { //var a=false;x=>a这种情况 } } else { _memberStack.Push(node.Member); } return(base.VisitMember(node)); }