8,497
社区成员
发帖
与我相关
我的任务
分享
#Region "动态构建Selector表达式"
#Region "BuildSelectorExpression"
''' <summary>
''' 动态构建Selector表达式返回查询表达式
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="sources"></param>
''' <param name="fields"></param>
''' <returns></returns>
<Runtime.CompilerServices.Extension>
Public Function SelectDynamic(Of T)(sources As IEnumerable(Of T), fields As IEnumerable(Of String)) As IEnumerable(Of Object)
Return sources.AsQueryable.Select(BuildSelectorExpression(Of T)(fields))
End Function
''' <summary>
''' 构建Selector表达式
''' </summary>
''' <param name="fields">需要选择的属性名称</param>
''' <returns>Selector表达式</returns>
<Runtime.CompilerServices.Extension>
Public Function BuildSelectorExpression(Of T)(fields As IEnumerable(Of String)) As Expression(Of Func(Of T, Object))
Dim Properties_dic As New Dictionary(Of String, PropertyInfo)(GetType(T).GetRuntimeProperties.Where(Function(p) fields.Contains(p.Name)).ToDictionary(Function(p) p.Name, Function(p) p))
Dim DynamicType As Type = LinqRuntimeTypeBuilder.GetDynamicType(Properties_dic.Values)
Dim Parameter As ParameterExpression = Expression.Parameter(GetType(T), "p")
Dim MemberBindings As IEnumerable(Of MemberBinding) = DynamicType.GetRuntimeProperties().Select(Function(p) Expression.Bind(p, Expression.Property(Parameter, Properties_dic(p.Name)))).OfType(Of MemberBinding)()
Return Expression.Lambda(Of Func(Of T, Object))(Expression.MemberInit(Expression.[New](DynamicType.GetConstructor(Type.EmptyTypes)), MemberBindings), Parameter)
End Function
#End Region
#Region "LinqRuntimeTypeBuilder"
Public NotInheritable Class LinqRuntimeTypeBuilder
Private Shared ReadOnly AssemblyName As New AssemblyName() With {.Name = "LinqRuntimeTypes"}
Private Shared ReadOnly ModuleBuilder As ModuleBuilder
Private Shared ReadOnly BuiltTypes_dic As New Dictionary(Of String, Type)()
Private Const RuntimeGetSetAttrs As MethodAttributes = MethodAttributes.Public Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig
Shared Sub New()
ModuleBuilder = AssemblyBuilder.DefineDynamicAssembly(AssemblyName, AssemblyBuilderAccess.Run).DefineDynamicModule(AssemblyName.Name)
End Sub
''' <summary>
''' BuildDynamicType
''' </summary>
''' <param name="properties_dic"></param>
''' <returns></returns>
Public Shared Function BuildDynamicType(properties_dic As Dictionary(Of String, Type)) As Type
If properties_dic Is Nothing Then Throw New ArgumentNullException(NameOf(properties_dic))
If properties_dic.Count = 0 Then Throw New ArgumentOutOfRangeException(NameOf(properties_dic), "必须至少一个字段")
Try
Monitor.Enter(BuiltTypes_dic)
Dim className As String = GetTypeKey(properties_dic)
If BuiltTypes_dic.ContainsKey(className) Then Return BuiltTypes_dic(className)
Dim TypeBuilder As TypeBuilder = ModuleBuilder.DefineType(className, TypeAttributes.Public Or TypeAttributes.Class Or TypeAttributes.Serializable)
With TypeBuilder
For Each prop As KeyValuePair(Of String, Type) In properties_dic
Dim PropertyBuilder As PropertyBuilder = .DefineProperty(name:=prop.Key, attributes:=PropertyAttributes.None, returnType:=prop.Value, parameterTypes:=Nothing)
Dim FieldBuilder As FieldBuilder = .DefineField("itheofield_" & prop.Key, prop.Value, FieldAttributes.Private)
Dim getMethodBuilder As MethodBuilder = .DefineMethod("get_" & prop.Key, RuntimeGetSetAttrs, prop.Value, Type.EmptyTypes)
Dim GetILGenerator As ILGenerator = getMethodBuilder.GetILGenerator()
With GetILGenerator
.Emit(OpCodes.Ldarg_0)
.Emit(OpCodes.Ldfld, FieldBuilder)
.Emit(OpCodes.Ret)
End With
Dim setMethodBuilder As MethodBuilder = TypeBuilder.DefineMethod("set_" & prop.Key, RuntimeGetSetAttrs, Nothing, New Type() {prop.Value})
Dim setILGenerator As ILGenerator = setMethodBuilder.GetILGenerator()
With setILGenerator
.Emit(OpCodes.Ldarg_0)
.Emit(OpCodes.Ldarg_1)
.Emit(OpCodes.Stfld, FieldBuilder)
.Emit(OpCodes.Ret)
End With
PropertyBuilder.SetGetMethod(getMethodBuilder)
PropertyBuilder.SetSetMethod(setMethodBuilder)
Next
BuiltTypes_dic(className) = .CreateType()
Return BuiltTypes_dic(className)
End With
Catch
Throw
Finally
Monitor.Exit(BuiltTypes_dic)
End Try
End Function
''' <summary>
''' GetTypeKey
''' </summary>
''' <param name="properties_dic"></param>
''' <returns></returns>
Private Shared Function GetTypeKey(properties_dic As Dictionary(Of String, Type)) As String
Return String.Join(";", properties_dic.Select(Function(p) p.Key & ";" & p.Value.Name).ToArray)
End Function
''' <summary>
''' GetDynamicType
''' </summary>
''' <param name="properties"></param>
''' <returns></returns>
Public Shared Function GetDynamicType(properties As IEnumerable(Of PropertyInfo)) As Type
Return BuildDynamicType(New Dictionary(Of String, Type)(properties.ToDictionary(Function(p) p.Name, Function(p) p.PropertyType)))
End Function
End Class
#End Region
#End Region
public static string GetPropName<T>(Expression<Func<T, object>> expr)
{
switch (expr.Body.NodeType)
{
case ExpressionType.MemberAccess:
return ((MemberExpression)expr.Body).Member.Name;
case ExpressionType.Convert:
return ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.Name;
case ExpressionType.New:
//new {} 的 解析在这里
return null;
default:
return null;
}
}
public static void RemoveModifiedStatus<TSource>(this DbContext context, TSource model, Expression<Func<TSource, object>> keySelector)
where TSource : class
{
//取得表达式
var expression = (new List<TSource>())
.AsQueryable()
.OrderBy(keySelector)
.Expression;
//取得表达式定义
//root.Nodes[1].Nodes[0].Nodes[0].Nodes
ExpressionTreeNode root = ExpressionTreeBuilder.GetExpressionTreeNode(expression);
if (root == null || root.Nodes[1] == null || root.Nodes[1].Nodes[0] == null || root.Nodes[1].Nodes[0].Nodes[0] == null || root.Nodes[1].Nodes[0].Nod
context.Entry(item).State = System.Data.Entity.EntityState.Modified;
context.RemoveModifiedStatus(item, c => new { c.CheckUserId, c.CheckTime, c.PublishTime, c.Guid });