/// <summary>
 /// Creates new instance of EndpointParameterDescriptor
 /// </summary>
 /// <param name="source">Source of Endpoint Parameter, Body, Route etc</param>
 /// <param name="parameterType">Parameter Object type</param>
 /// <param name="name">Name of parameter</param>
 /// <param name="isOptional">If Parameter is optional</param>
 public EndpointParameterDescriptor(EndpointParameterSource source, Type parameterType, string name, bool isOptional = false)
 {
     Source        = source;
     ParameterType = parameterType;
     Name          = name;
     IsOptional    = isOptional;
 }
 private static (SyncParameterFactory factory, EndpointParameterDescriptor[] info) GetParameterInfoForClassProperty(PropertyInfo propertyInfo, EndpointParameterSource source, EndpointDeclarationFactoryOptions options)
 {
     return(ParameterBinder.GetParameterDeclaration(propertyInfo.Name, propertyInfo.PropertyType, true, null, source, propertyInfo.PropertyType.IsArray, options));
 }
        public static (SyncParameterFactory factory, EndpointParameterDescriptor[] info) GetParameterDeclarationForClass(Type type, EndpointParameterSource source, EndpointDeclarationFactoryOptions options)
        {
            var constructor = type.GetConstructor(Array.Empty <Type>());

            if (constructor is null)
            {
                throw new InvalidEndpointSetupException($"No parameterless constructor for {type}");
            }
            var properties             = type.GetProperties().Where(IsValidProperty).ToArray();
            var parameterInfos         = properties.Select(p => GetParameterInfoForClassProperty(p, source, options)).ToArray();
            var stateVariable          = Expression.Variable(typeof(byte), "ee_state");
            var propertyStateVariable  = Expression.Variable(typeof(byte), "ee_propetyState");
            var resultVariable         = Expression.Variable(type, "ee_result");
            var propertyResultVariable = Expression.Variable(typeof(ParameterBindingResult), "ee_propertyResult");

            var ctor             = Expression.New(constructor);
            var blockExpressions = new List <Expression>
            {
                Expression.Assign(stateVariable, Expression.Constant(none)),
                Expression.Assign(resultVariable, ctor)
            };

            for (var i = 0; i < properties.Length; i++)
            {
                blockExpressions.AddRange(BuildPropertyAssignment(properties[i], parameterInfos[i].factory, resultVariable, stateVariable, propertyResultVariable, propertyStateVariable));
            }

            blockExpressions.Add(Expression.New(parameterBindingResultCtor, resultVariable, Expression.Convert(stateVariable, typeof(ParameterBindingIssues))));
            var block   = Expression.Block(typeof(ParameterBindingResult), new[] { stateVariable, resultVariable, propertyResultVariable, propertyStateVariable }, blockExpressions);
            var factory = Expression.Lambda <SyncParameterFactory>(block, ctxParameterExpr, optionsParameterExpr, errorCollectionParameterExpr);

            return(factory.Compile(), parameterInfos.SelectMany(s => s.info).ToArray());
        }
Ejemplo n.º 4
0
 private static SyncParameterFactory GetParameterFactory <T>(string parameterName, IParser <T> parsable, bool allowNull, bool isNullable, object?defaultValue, EndpointParameterSource parameterSource, bool isArray)
 {
     return((parameterSource, isArray) switch
     {
         (EndpointParameterSource.Query, false) => GetParameterFactoryForQuery <T>(parameterName, parsable, allowNull, isNullable, defaultValue),
         (EndpointParameterSource.Query, true) => GetParameterFactoryForQueryArray <T>(parameterName, parsable),
         (EndpointParameterSource.Header, false) => GetParameterFactoryForHeader <T>(parameterName, parsable, allowNull, isNullable, defaultValue),
         (EndpointParameterSource.Header, true) => GetParameterFactoryForHeaderArray <T>(parameterName, parsable),
         (EndpointParameterSource.Route, false) => GetParameterFactoryForRoute <T>(parameterName, parsable),
         _ => throw new InvalidEndpointSetupException($"Cannot bind for {parameterSource} and IsArray {isArray}")
     });
Ejemplo n.º 5
0
        private static SyncParameterFactory GetParameterFactory(string parameterName, Type type, bool allowNull, bool isNullable, object?defaultValue, EndpointParameterSource parameterSource, bool isArray, EndpointDeclarationFactoryOptions options)
        {
            if (type == typeof(string))
            {
                return(GetParameterFactoryForStringValue(parameterName, defaultValue, parameterSource, isArray));
            }

            if (!options.Parsers.TryGetParser(type, out var parser))
            {
                throw new InvalidEndpointSetupException($"Could not parse route ({parameterName}), cannot parse {type}");
            }

#pragma warning disable S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
            var method = typeof(ParameterBinder).GetMethods(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
                         .Single(w => w.Name == nameof(GetParameterFactory) && w.ContainsGenericParameters)
                         .MakeGenericMethod(type);
#pragma warning restore S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields

            var result = (SyncParameterFactory)method.Invoke(null, new[] { parameterName, parser, allowNull, isNullable, defaultValue, parameterSource, isArray }) !;
            return(result);
        }
Ejemplo n.º 6
0
        public static (SyncParameterFactory factory, EndpointParameterDescriptor[] info) GetParameterDeclaration(string parameterName, Type type, bool hasDefaultValue, object?defaultValue, EndpointParameterSource paramterSource, bool isArray, EndpointDeclarationFactoryOptions options)
        {
            if (IsComplex(type, options))
            {
                return(ComplexParameterBinder.GetParameterDeclarationForClass(type, paramterSource, options));
            }
            var parameterType = type;
            var allowNull     = hasDefaultValue;
            var isNullable    = false;

            if (!isArray && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                isNullable = true;
                allowNull  = true;
                if (!hasDefaultValue)
                {
                    defaultValue = null;
                }
                parameterType = type.GetGenericArguments()[0];
            }
            if (isArray)
            {
                allowNull     = false;
                parameterType = type.GetElementType() !;
            }
            var parameterFactory = GetParameterFactory(parameterName, parameterType, allowNull, isNullable, defaultValue, paramterSource, isArray, options);

            return(parameterFactory, new[] { new EndpointParameterDescriptor(paramterSource, type, parameterName, allowNull) });
        }