public ReflectionInvoker(Type type, string name) { Name = name; List = TypeHelper.GetMemberInfoList(type, name); Last = List.Last(); DataType = TypeHelper.GetMemberType(Last); TargetType = type; }
public static Func <T, V> GetInvokerGet(string name, List <MemberInfo> list) { var first = list.First(); var method = new DynamicMethod($"{first.DeclaringType.Name}.{name}Get", typeof(V), new Type[] { typeof(T) }, true); ILGenerator il = method.GetILGenerator(); var locals = new LocalBuilder[list.Count]; var lables = new Label[(list.Count - 1) * 2]; for (int i = 0; i < list.Count; i++) { var info = list[i]; locals[i] = il.DeclareLocal(TypeHelper.GetMemberType(info)); } for (int i = 0; i < lables.Length; i++) { var info = list[i / 2]; if (!TypeHelper.GetMemberType(info).IsValueType) { lables[i] = il.DefineLabel(); } } EmitLoadArgument(il, typeof(T)); int j = 0; for (int i = 0; i < list.Count; i++) { var info = list[i]; var type = TypeHelper.GetMemberType(info); EmitCallGet(il, info); if (i < list.Count - 1) { il.Emit(OpCodes.Stloc, locals[i]); if (!type.IsValueType) { il.Emit(OpCodes.Ldloc, locals[i]); il.Emit(OpCodes.Brtrue_S, lables[j + 1]); il.MarkLabel(lables[j++]); il.Emit(OpCodes.Ldloc, locals[list.Count - 1]); il.Emit(OpCodes.Ret); il.MarkLabel(lables[j++]); } EmitLoadLocal(il, locals[i]); } } il.Emit(OpCodes.Ret); return((Func <T, V>)method.CreateDelegate(typeof(Func <T, V>))); }
public static IInvoker Initialize(Type type, string property) { if (property == null) return null; var list = TypeHelper.GetMemberInfoList(type, property); if (list.Count == 1) { return Initialize(list[0].Info, list[0].Index == null, list[0].Index); } if (list.Count > 1) { var last = list.Last(); var emittype = typeof(ComplexInvoker<,>).MakeGenericType(type, TypeHelper.GetMemberType(last.Info)); return (IInvoker)CreateObject(emittype, new[] { typeof(string), typeof(List<MemberParseInfo>) }, new object[] { property, list }, true); } return null; }
//https://stackoverflow.com/a/39617419/4682355 public static Expression CreateNullPropagationExpression(Expression o, Expression call, MemberInfo memberInfo) { Expression propertyAccess = call; var propertyType = TypeHelper.GetMemberType(memberInfo); if (propertyType.IsValueType && !TypeHelper.IsNullable(propertyType)) { return(propertyAccess); } var nullResult = Expression.Default(propertyAccess.Type); var condition = Expression.Equal(o, Expression.Constant(null, o.Type)); return(Expression.Condition(condition, nullResult, propertyAccess)); }
public static Action <T, V> GetInvokerSet(string name, List <MemberInfo> list) { var last = list.Last(); foreach (var item in list) { if (item is PropertyInfo && ((PropertyInfo)item).PropertyType.IsValueType && (!((PropertyInfo)item).CanWrite || ((PropertyInfo)item).GetSetMethod() == null)) { return(null); } } if (last is MethodInfo || (last is PropertyInfo && (!((PropertyInfo)last).CanWrite || ((PropertyInfo)last).GetSetMethod() == null))) { return(null); } var first = list.First(); DynamicMethod method = new DynamicMethod($"{first.DeclaringType.Name}.{name}Set", typeof(void), new Type[] { typeof(T), typeof(V) }, true); var il = method.GetILGenerator(); var locals = new LocalBuilder[list.Count - 1]; var lables = new Label[list.Count + 1]; for (int i = 0; i < list.Count - 1; i++) { var info = list[i]; locals[i] = il.DeclareLocal(TypeHelper.GetMemberType(info)); } for (int i = 0; i <= list.Count; i++) { lables[i] = il.DefineLabel(); } EmitLoadArgument(il, typeof(T)); int j = 0; for (int i = 0; i < list.Count; i++) { var info = list[i]; var type = TypeHelper.GetMemberType(info); if (i < list.Count - 1) { EmitCallGet(il, info); il.Emit(OpCodes.Stloc, locals[i]); if (!type.IsValueType) { il.Emit(OpCodes.Ldloc, locals[i]); il.Emit(OpCodes.Brfalse_S, lables[lables.Length - 1]); il.MarkLabel(lables[j++]); } EmitLoadLocal(il, locals[i]); } else { il.Emit(OpCodes.Ldarg_1); EmitCallSet(il, info); for (int r = list.Count - 2; r >= 0; r--) { info = list[r]; type = TypeHelper.GetMemberType(info); if (type.IsValueType) { if (r == 0) { EmitLoadArgument(il, typeof(T)); } else { EmitLoadLocal(il, locals[r - 1]); } il.Emit(OpCodes.Ldloc, locals[r]);//EmitLoadLocal(il, locals[r]); EmitCallSet(il, info); } } } } if (j > 0) { il.MarkLabel(lables[lables.Length - 1]); } il.Emit(OpCodes.Ret); var handler = (Action <T, V>)method.CreateDelegate(typeof(Action <T, V>)); return(handler); }
public static Action <T, V> GetExpressionSet(string name, List <MemberParseInfo> list) { var last = list.Last(); var first = list.First(); var target = Expression.Parameter(typeof(T), "target"); var value = Expression.Parameter(typeof(V), "value"); var returnLabel = Expression.Label(); var locals = new ParameterExpression[list.Count - 1]; var labels = new LabelTarget[list.Count]; List <Expression> body = new List <Expression>(); for (int i = 0; i < list.Count - 1; i++) { var info = list[i]; locals[i] = Expression.Variable(TypeHelper.GetMemberType(info.Info), info.Info.Name.ToLower()); } for (int i = 0; i < list.Count; i++) { labels[i] = Expression.Label(); } int j = 0; for (int i = 0; i < list.Count; i++) { var info = list[i]; var type = TypeHelper.GetMemberType(info.Info); if (i < list.Count - 1) { var call = Call(i == 0 ? target : locals[i - 1], info, i); body.Add(Expression.Assign(locals[i], call)); if (!type.IsValueType || TypeHelper.IsNullable(type)) { body.Add(Expression.IfThenElse(Expression.Equal(locals[i], Expression.Constant(null, type)), Expression.Return(returnLabel), Expression.Label(labels[j++]))); } } else { for (int r = list.Count - 1; r >= 0; r--) { info = list[r]; type = TypeHelper.GetMemberType(info.Info); if (type.IsValueType || r == list.Count - 1) { var param = r == 0 ? target : locals[r - 1]; var setValue = r == list.Count - 1 ? value : locals[r]; if (TypeHelper.CanWrite(info.Info)) { var call = Call(param, info, r); body.Add(Expression.Assign(call, setValue)); } else { return(null); } } } } } if (j > 0) { body.Add(Expression.Label(returnLabel)); } return(Expression.Lambda <Action <T, V> >(Expression.Block(locals, body), target, value).Compile()); }