Beispiel #1
0
 public ReflectionInvoker(Type type, string name)
 {
     Name       = name;
     List       = TypeHelper.GetMemberInfoList(type, name);
     Last       = List.Last();
     DataType   = TypeHelper.GetMemberType(Last);
     TargetType = type;
 }
Beispiel #2
0
        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>)));
        }
Beispiel #3
0
 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;
 }
Beispiel #4
0
        //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));
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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());
        }