using System.Collections; using System.ComponentModel.DataAnnotations.Schema; using System.Linq.expressions; using System.Reflection; using static System.Linq.expressions.expression; public static class QueryableExtentions
{ public static IQueryable Select(this IQueryable
调用方法如下,先构造测试类
public partial class User
{ public int Id { get; set; }
[Required]
[StringLength(50)] public string Name { get; set; } public int RoleId { get; set; }
[ForeignKey(nameof(RoleId))] public virtual Role Role { get; set; }
}
public partial class Role
{ public int Id { get; set; } public string Name { get; set; } public int DepartmentId { get; set; }
[ForeignKey(nameof(DepartmentId))] public virtual Department Department { get; set; }
} public partial class Department
{ public int Id { get; set; }
[Required]
[StringLength(50)] public string Name { get; set; }
}
public partial class UserModel
{ public string Name { get; set; } public string RoleName { get; set; } //[FromEntity("Name","Role")] //public string RoleName1 { get; set; }
[FromEntity("Name", "Department", "Role")] public string DepartmentName { get; set; } //public virtual RoleModel Role { get; set; } //[FromEntity("Department", "Role")] //public virtual Department Department { get; set; }
}
查询代码如下
static void Main(string[] args)
{ using (var context = new TestContext())
{ var list = context.User.Select().ToList();
}
Console.WriteLine($"------------结束--------------------");
Console.ReadLine();
}
public partial class UserModel
{ public string Name { get; set; } public string RoleName { get; set; }
[FromEntity("Name","Role")] public string RoleName1 { get; set; }
[FromEntity("Name", "Department", "Role")] public string DepartmentName { get; set; } public virtual RoleModel Role { get; set; }
[FromEntity("Department", "Role")] public virtual Department Department { get; set; }
} public partial class RoleModel
{ public string Name { get; set; } public string DepartmentName { get; set; } public virtual DepartmentModel Department { get; set; }
} public partial class DepartmentModel
{ public string Name { get; set; }
}
using System.Collections; using System.ComponentModel.DataAnnotations.Schema; using System.Linq.expressions; using System.Reflection; using static System.Linq.expressions.expression; public static class QueryableExtentions
{ public static IQueryable Select(this IQueryable query)
{ return Queryable.Select(query, GetLamda(query.GetType().GetGenericArguments()[0]));
} public static IQueryable Select(this IQueryable query)
{ return Queryable.Select(query, GetLamda());
} public static expression> GetLamda(Type type = null)
{ var sourceType = typeof(TSource); var targetType = typeof(TTarget); var parameter = Parameter(sourceType);
expression propertyParameter; if (type != null)
{
propertyParameter = Convert(parameter, type);
sourceType = type;
} else
propertyParameter = parameter; return Lambda>(Getexpression(propertyParameter, sourceType, targetType), parameter);
} public static MemberInitexpression Getexpression(expression parameter, Type sourceType, Type targetType)
{ var memberBindings = new List(); foreach (var targetItem in targetType.GetProperties().Where(x => x.CanWrite))
{ var fromEntityAttr = targetItem.GetCustomAttribute(); if (fromEntityAttr != null)
{ var property = GetFromEntityexpression(parameter, sourceType, fromEntityAttr); if (property != null)
memberBindings.Add(Bind(targetItem, property)); continue;
} var sourceItem = sourceType.GetProperty(targetItem.Name); if (sourceItem == null)//当没有对应的属性时,查找 实体名+属性 { var complexSourceItemProperty = GetCombinationexpression(parameter, sourceType, targetItem); if (complexSourceItemProperty != null)
memberBindings.Add(Bind(targetItem, complexSourceItemProperty)); continue;
} //判断实体的读写权限
if (sourceItem == null || !sourceItem.CanRead) continue; //标注NotMapped特性的属性忽略转换
if (sourceItem.GetCustomAttribute() != null) continue; var sourceProperty = Property(parameter, sourceItem); //当非值类型且类型不相同时
if (!sourceItem.PropertyType.IsValueType && sourceItem.PropertyType != targetItem.PropertyType && targetItem.PropertyType != targetType)
{ //判断都是(非泛型、非数组)class
if (sourceItem.PropertyType.IsClass && targetItem.PropertyType.IsClass && !sourceItem.PropertyType.IsArray && !targetItem.PropertyType.IsArray && !sourceItem.PropertyType.IsGenericType && !targetItem.PropertyType.IsGenericType)
{ var expression = Getexpression(sourceProperty, sourceItem.PropertyType, targetItem.PropertyType);
memberBindings.Add(Bind(targetItem, expression));
} continue;
} if (targetItem.PropertyType != sourceItem.PropertyType) continue;
memberBindings.Add(Bind(targetItem, sourceProperty));
} return MemberInit(New(targetType), memberBindings);
} ///
/// 根据FromEntityAttribute 的值获取属性对应的路径 ///
///
///
///
///
private static expression GetFromEntityexpression(expression sourceProperty, Type sourceType, FromEntityAttribute fromEntityAttribute)
{ var findType = sourceType; var resultProperty = sourceProperty; var tableNames = fromEntityAttribute.EntityNames; if (tableNames == null)
{ var columnProperty = findType.GetProperty(fromEntityAttribute.EntityColuum); if (columnProperty == null) return null; else
return Property(resultProperty, columnProperty);
} for (int i = tableNames.Length - 1; i >= 0; i--)
{ var tableProperty = findType.GetProperty(tableNames[i]); if (tableProperty == null) return null;
findType = tableProperty.PropertyType;
resultProperty = Property(resultProperty, tableProperty);
} var property = findType.GetProperty(fromEntityAttribute.EntityColuum); if (property == null) return null; else
return Property(resultProperty, property);
} ///
/// 根据组合字段获取其属性路径 ///
///
///
///
///
private static expression GetCombinationexpression(expression sourceProperty, Type sourceType, PropertyInfo targetItem)
{ foreach (var item in sourceType.GetProperties().Where(x => x.CanRead))
{ if (targetItem.Name.StartsWith(item.Name))
{ if (item != null && item.CanRead && item.PropertyType.IsClass && !item.PropertyType.IsGenericType)
{ var rightName = targetItem.Name.Substring(item.Name.Length); var complexSourceItem = item.PropertyType.GetProperty(rightName); if (complexSourceItem != null && complexSourceItem.CanRead) return Property(Property(sourceProperty, item), complexSourceItem);
}
}
} return null;
}
} ///
/// 用于标注字段 来自哪个表的的哪一列(仅限于有关联的表中) ///
public class FromEntityAttribute : Attribute
{ ///
/// 类名(表名) ///
public string[] EntityNames { get; } ///
/// 字段(列名) ///
public string EntityColuum { get; } ///
/// 列名 + 该列的表名 + 该列的表的上一级表名 ///
///
///
public FromEntityAttribute(string entityColuum, params string[] entityNames)
{
EntityNames = entityNames;
EntityColuum = entityColuum;
}
}
调用方法如下,先构造测试类
public partial class User
{ public int Id { get; set; }
[Required]
[StringLength(50)] public string Name { get; set; } public int RoleId { get; set; }
[ForeignKey(nameof(RoleId))] public virtual Role Role { get; set; }
}
public partial class Role
{ public int Id { get; set; } public string Name { get; set; } public int DepartmentId { get; set; }
[ForeignKey(nameof(DepartmentId))] public virtual Department Department { get; set; }
} public partial class Department
{ public int Id { get; set; }
[Required]
[StringLength(50)] public string Name { get; set; }
}
public partial class UserModel
{ public string Name { get; set; } public string RoleName { get; set; } //[FromEntity("Name","Role")] //public string RoleName1 { get; set; }
[FromEntity("Name", "Department", "Role")] public string DepartmentName { get; set; } //public virtual RoleModel Role { get; set; } //[FromEntity("Department", "Role")] //public virtual Department Department { get; set; }
}
查询代码如下
static void Main(string[] args)
{ using (var context = new TestContext())
{ var list = context.User.Select().ToList();
}
Console.WriteLine($"------------结束--------------------");
Console.ReadLine();
}
public partial class UserModel
{ public string Name { get; set; } public string RoleName { get; set; }
[FromEntity("Name","Role")] public string RoleName1 { get; set; }
[FromEntity("Name", "Department", "Role")] public string DepartmentName { get; set; } public virtual RoleModel Role { get; set; }
[FromEntity("Department", "Role")] public virtual Department Department { get; set; }
} public partial class RoleModel
{ public string Name { get; set; } public string DepartmentName { get; set; } public virtual DepartmentModel Department { get; set; }
} public partial class DepartmentModel
{ public string Name { get; set; }
}