예제 #1
0
        private static void AppendValue(Context context, Expression prop, UriToken token)
        {
            Type       actualType        = Nullable(prop.Type);
            MethodInfo formattableMethod = actualType == prop.Type
                ? MethodOfTemplateCompiler_ToStringFormattable
                : MethodOfTemplateCompiler_NullableToStringFormattable;
            MethodInfo toStringMethod = actualType == prop.Type
                ? MethodOfTemplateCompiler_ToString
                : MethodOfTemplateCompiler_NullableToString;

            Expression toString;

            if (TypeofIFormattable.IsAssignableFrom(actualType))
            {
                MethodInfo method = formattableMethod.MakeGenericMethod(actualType);
                toString = Expression.Call(null, method, prop, token.FormatConstant, token.DefaultConstant);
            }
            else
            {
                MethodInfo method = toStringMethod.MakeGenericMethod(actualType);
                toString = Expression.Call(null, method, prop, token.DefaultConstant);
            }
            toString = Expression.Call(QueryBuilder, MethodofUrlBuilder_Append, toString);
            context.Add(toString);
        }
예제 #2
0
        private static void AppendQuery(Context context, UriQuery query)
        {
            if (query.Value.Count == 1 && query.Value[0].Type != UriTokenType.Literal)
            {
                UriToken         value    = query.Value[0];
                MemberExpression prop     = Expression.PropertyOrField(context.Target, value.Name);
                Type             propType = Nullable(prop.Type);

                if (value.Type == UriTokenType.Collection)
                {
                    MethodInfo getEnumerator = Enumerator(propType);
                    if (getEnumerator != null)
                    {
                        AppendCollection(context, prop, getEnumerator, query.Name, value);
                    }
                    else
                    {
                        throw new InvalidOperationException(Invariant($"An enumerable was expected for {value.Name}."));
                    }
                    return;
                }

                if (value.SubName != null)
                {
                    if (propType.IsEnum)
                    {
                        AppendEnum(context, prop, query.Name, value);
                    }
                    else
                    {
                        throw new InvalidOperationException(Invariant($"An enum was expected for {value.Name}."));
                    }
                    return;
                }

                if (value.Default == null)
                {
                    AppendNullable(context, prop, query.Name, value);
                    return;
                }
            }

            context.Add(Expression.Call(QueryBuilder, MethodofUrlBuilder_StartParameter));

            for (var i = 0; i < query.Name.Count; i++)
            {
                AppendToken(context, query.Name[i]);
            }

            context.Add(Expression.Call(QueryBuilder, MethodofUrlBuilder_StartValue));
            for (var i = 0; i < query.Value.Count; i++)
            {
                AppendToken(context, query.Value[i]);
            }
        }
예제 #3
0
 private static void AppendToken(Context context, UriToken token)
 {
     if (token.Type == UriTokenType.Literal)
     {
         context.Add(Expression.Call(QueryBuilder, MethodofUrlBuilder_Append, token.DefaultConstant));
     }
     else
     {
         Expression prop = Expression.PropertyOrField(context.Target, token.Name);
         AppendValue(context, prop, token);
     }
 }
예제 #4
0
        private static void AppendCollection(Context context, MemberExpression prop, MethodInfo getEnumerator, IReadOnlyList <UriToken> name, UriToken value)
        {
            Expression           nonNull          = Nullable(prop);
            MethodCallExpression createEnumerator = Expression.Call(nonNull, getEnumerator, null);
            ParameterExpression  enumerator       = context.Add(createEnumerator.Type, "e");
            MemberExpression     current          = Expression.Property(enumerator, nameof(System.Collections.IEnumerator.Current));
            MethodCallExpression moveNext         = Expression.Call(enumerator, MethodofIEnumerator_MoveNext, null);
            List <Expression>    statements       = StartQueryParameter(context, name);

            AppendValue(context.With(statements), current, value);

            LabelTarget    brk  = Expression.Label("Exit " + prop.Member.Name);
            LoopExpression loop = Expression.Loop(
                Expression.IfThenElse(
                    moveNext,
                    Expression.Block(statements),
                    Expression.Break(brk)),
                brk
                );

            TryExpression t = Expression.TryFinally(
                Expression.Block(
                    Expression.Assign(enumerator, createEnumerator),
                    loop),
                Expression.Call(enumerator, MethodofIDisposable_Dispose)
                );

            context.Add(IsNull(prop, t));
        }
예제 #5
0
        private static void AppendEnum(Context context, MemberExpression prop, IReadOnlyList <UriToken> name, UriToken value)
        {
            Expression         nonNull    = Nullable(prop);
            var                isFlags    = nonNull.Type.GetCustomAttribute <FlagsAttribute>() != null;
            ConstantExpression enumMember = Expression.Constant(Enum.Parse(nonNull.Type, value.SubName));
            List <Expression>  statements = StartQueryParameter(context, name);

            if (value.Default != null)
            {
                statements.Add(Expression.Call(QueryBuilder, MethodofUrlBuilder_Append, value.DefaultConstant));
            }

            Expression condition = isFlags
                ? (Expression)Expression.Call(enumMember, MethodofEnum_HasFlag, Expression.Convert(enumMember, TypeofEnum))
                : Expression.Equal(nonNull, enumMember);

            condition = Expression.IfThen(condition, Expression.Block(statements));

            context.Add(IsNull(prop, condition));
        }
예제 #6
0
        private static void AppendNullable(Context context, MemberExpression prop, IReadOnlyList <UriToken> name, UriToken value)
        {
            List <Expression> statements = StartQueryParameter(context, name);

            AppendValue(context.With(statements), prop, value);

            context.Add(IsNull(prop, Expression.Block(statements)));
        }