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); }
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]); } }
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); } }
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)); }
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)); }
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))); }