示例#1
0
        public static void EmitNullableExpression(this CompilationContext context, LocalBuilder local,
                                                  Action <CompilationContext> nonNullExpression, Action <CompilationContext> nullExpression)
        {
            var label = context.DefineLabel();

            if (local.LocalType.IsNullable())
            {
                var variableType = local.LocalType.GetTypeInfo();
                context.Emit(OpCodes.Ldloca, local);
                context.EmitCall(variableType.GetProperty("HasValue").GetGetMethod());
                context.Emit(OpCodes.Brfalse, label);

                context.Emit(OpCodes.Ldloca, local);
                context.EmitCall(variableType.GetProperty("Value").GetGetMethod());
                context.CurrentType = variableType.GetGenericArguments()[0];
            }
            else
            {
                context.Emit(OpCodes.Ldloc, local);
                context.Emit(OpCodes.Ldnull);
                context.EmitCall(_referenceEqualsMethod);
                context.Emit(OpCodes.Brtrue, label);

                context.Emit(OpCodes.Ldloc, local);
                context.CurrentType = local.LocalType;
            }
            nonNullExpression(context);

            var labelEnd = context.DefineLabel();

            context.Emit(OpCodes.Br, labelEnd);

            context.MakeLabel(label);
            nullExpression(context);

            context.MakeLabel(labelEnd);
        }
示例#2
0
 public void Emit(CompilationContext context)
 {
     context.EmitCall(_invokeMethod);
     context.CurrentType = typeof(IEnumerable <TTarget>);
 }
示例#3
0
 public void Emit(CompilationContext context)
 {
     context.EmitCall(_invokeMethod);
 }
示例#4
0
 public void Emit(CompilationContext context)
 {
     context.EmitCall(_invokeMethod);
     context.CurrentType = null;
 }
示例#5
0
 public void Emit(CompilationContext context)
 {
     context.EmitCall(_invokeMethod);
     context.CurrentType = typeof(TResult);
 }
示例#6
0
        public static void EmitDefault(this CompilationContext context, Type targetType)
        {
            var originalType = targetType;

            if (targetType.IsNullable())
            {
                var local = context.DeclareLocal(targetType);
                context.Emit(OpCodes.Ldloca, local);
                context.Emit(OpCodes.Initobj, targetType);
                context.Emit(OpCodes.Ldloc, local);
                context.CurrentType = originalType;
                return;
            }
            if (!targetType.GetTypeInfo().IsValueType)
            {
                context.Emit(OpCodes.Ldnull);
                context.CurrentType = originalType;
                return;
            }
            if (targetType.GetTypeInfo().IsEnum)
            {
                targetType = Enum.GetUnderlyingType(targetType);
            }
            if (targetType == typeof(int) || targetType == typeof(uint) ||
                targetType == typeof(short) || targetType == typeof(ushort) ||
                targetType == typeof(byte) || targetType == typeof(sbyte) ||
                targetType == typeof(char) || targetType == typeof(bool))
            {
                context.Emit(OpCodes.Ldc_I4_0);
                context.CurrentType = originalType;
                return;
            }
            if (targetType == typeof(long) || targetType == typeof(ulong))
            {
                context.Emit(OpCodes.Ldc_I4_0);
                context.Emit(OpCodes.Conv_I8);
                context.CurrentType = originalType;
                return;
            }
            if (targetType == typeof(float))
            {
                context.Emit(OpCodes.Ldc_I4_0);
                context.Emit(OpCodes.Conv_R4);
                context.CurrentType = originalType;
                return;
            }
            if (targetType == typeof(double))
            {
                context.Emit(OpCodes.Ldc_I4_0);
                context.Emit(OpCodes.Conv_R8);
                context.CurrentType = originalType;
                return;
            }
            Func <MethodInfo, bool> coverterPredicate = method =>
            {
                if (method.Name == "op_Implicit")
                {
                    var parameters = method.GetParameters();
                    return(parameters.Length == 1 && parameters[0].ParameterType == typeof(int));
                }
                return(false);
            };
            var reflectingType = targetType.GetTypeInfo();

            if (targetType == typeof(decimal))
            {
                context.Emit(OpCodes.Ldc_I4_0);
                context.EmitCall(reflectingType.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(coverterPredicate));
                context.CurrentType = originalType;
                return;
            }
            var field = reflectingType.GetField("Empty", BindingFlags.Public | BindingFlags.Static) ??
                        reflectingType.GetField("Zero", BindingFlags.Public | BindingFlags.Static) ??
                        reflectingType.GetField("MinValue", BindingFlags.Public | BindingFlags.Static);

            if (field != null)
            {
                context.Emit(OpCodes.Ldsfld, field);
                context.CurrentType = field.FieldType;
                context.EmitCast(originalType);
                return;
            }
            var property = reflectingType.GetProperty("Empty", BindingFlags.Public | BindingFlags.Static) ??
                           reflectingType.GetProperty("Zero", BindingFlags.Public | BindingFlags.Static) ??
                           reflectingType.GetProperty("MinValue", BindingFlags.Public | BindingFlags.Static);
            var getMethod = property?.GetGetMethod();

            if (getMethod != null)
            {
                context.EmitCall(getMethod);
                context.CurrentType = getMethod.ReturnType;
                context.EmitCast(originalType);
                return;
            }
            var targetLocal = context.DeclareLocal(targetType);

            context.Emit(OpCodes.Ldloca, targetLocal);
            context.Emit(OpCodes.Initobj, targetType);
            context.Emit(OpCodes.Ldloc, targetLocal);
            context.CurrentType = originalType;
        }