Ejemplo n.º 1
0
            public static ExactBinding <TMessage> TryBuild(
                AsyncCollectorBindingProvider <TAttribute, TType> parent,
                Mode mode,
                BindingProviderContext context)
            {
                var patternMatcher = parent._patternMatcher;

                var        parameter       = context.Parameter;
                TAttribute attributeSource = parameter.GetCustomAttribute <TAttribute>(inherit: false);

                Func <TAttribute, Task <TAttribute> > hookWrapper = null;

                if (parent.PostResolveHook != null)
                {
                    hookWrapper = (attrResolved) => parent.PostResolveHook(attrResolved, parameter, parent._nameResolver);
                }

                Func <object, object> buildFromAttribute;
                FuncConverter <TMessage, TAttribute, TType> converter = null;

                // Prefer the shortest route to creating the user type.
                // If TType matches the user type directly, then we should be able to directly invoke the builder in a single step.
                //   TAttribute --> TUserType
                var checker = ConverterManager.GetTypeValidator <TType>();

                if (checker.IsMatch(typeof(TMessage)))
                {
                    buildFromAttribute = patternMatcher.TryGetConverterFunc(
                        typeof(TAttribute), typeof(IAsyncCollector <TMessage>));
                }
                else
                {
                    var converterManager = parent._converterManager;

                    // Try with a converter
                    // Find a builder for :   TAttribute --> TType
                    // and then couple with a converter:  TType --> TParameterType
                    converter = converterManager.GetConverter <TMessage, TType, TAttribute>();
                    if (converter == null)
                    {
                        // Preserves legacy behavior. This means we can only have 1 async collector.
                        // However, the collector's builder object can switch.
                        throw NewMissingConversionError(typeof(TMessage));
                    }

                    buildFromAttribute = patternMatcher.TryGetConverterFunc(
                        typeof(TAttribute), typeof(IAsyncCollector <TType>));
                }

                if (buildFromAttribute == null)
                {
                    return(null);
                }

                ParameterDescriptor param;

                if (parent.BuildParameterDescriptor != null)
                {
                    param = parent.BuildParameterDescriptor(attributeSource, parameter, parent._nameResolver);
                }
                else
                {
                    param = new ParameterDescriptor
                    {
                        Name         = parameter.Name,
                        DisplayHints = new ParameterDisplayHints
                        {
                            Description = "output"
                        }
                    };
                }

                var cloner = new AttributeCloner <TAttribute>(attributeSource, context.BindingDataContract, parent._nameResolver, hookWrapper);

                return(new ExactBinding <TMessage>(cloner, param, mode, buildFromAttribute, converter));
            }
Ejemplo n.º 2
0
        // Parse the signature to determine which mode this is.
        // Can also check with converter manager to disambiguate some cases.
        private CollectorBindingPattern GetMode(ParameterInfo parameter)
        {
            Type parameterType = parameter.ParameterType;

            if (parameterType.IsGenericType)
            {
                var genericType = parameterType.GetGenericTypeDefinition();
                var elementType = parameterType.GetGenericArguments()[0];

                if (genericType == typeof(IAsyncCollector <>))
                {
                    return(new CollectorBindingPattern(Mode.IAsyncCollector, elementType));
                }
                else if (genericType == typeof(ICollector <>))
                {
                    return(new CollectorBindingPattern(Mode.ICollector, elementType));
                }

                // A different interface. Let another rule try it.
                return(null);
            }

            if (parameter.IsOut)
            {
                // How should "out byte[]" bind?
                // If there's an explicit "byte[] --> TMessage" converter, then that takes precedence.
                // Else, bind over an array of "byte --> TMessage" converters
                Type elementType  = parameter.ParameterType.GetElementType();
                bool hasConverter = this._converterManager.HasConverter <TAttribute>(elementType, typeof(TType));
                if (hasConverter)
                {
                    // out T, where T might be an array
                    return(new CollectorBindingPattern(Mode.OutSingle, elementType));
                }

                if (elementType.IsArray)
                {
                    // out T[]
                    var messageType = elementType.GetElementType();
                    return(new CollectorBindingPattern(Mode.OutArray, messageType));
                }

                var validator = ConverterManager.GetTypeValidator <TType>();
                if (validator.IsMatch(elementType))
                {
                    // out T, t is not an array
                    return(new CollectorBindingPattern(Mode.OutSingle, elementType));
                }

                // For out-param ,we don't expect another rule to claim it. So give some rich errors on mismatch.
                if (typeof(IEnumerable).IsAssignableFrom(elementType))
                {
                    throw new InvalidOperationException(
                              "Enumerable types are not supported. Use ICollector<T> or IAsyncCollector<T> instead.");
                }
                else if (typeof(object) == elementType)
                {
                    throw new InvalidOperationException("Object element types are not supported.");
                }
            }

            // No match. Let another rule claim it
            return(null);
        }
Ejemplo n.º 3
0
            public static ExactBinding <TUserType> TryBuild(
                BindToInputBindingProvider <TAttribute, TType> parent,
                BindingProviderContext context)
            {
                var cm             = parent._converterManager;
                var patternMatcher = parent._patternMatcher;

                var        parameter       = context.Parameter;
                TAttribute attributeSource = parameter.GetCustomAttribute <TAttribute>(inherit: false);

                Func <TAttribute, Task <TAttribute> > hookWrapper = null;

                if (parent.PostResolveHook != null)
                {
                    hookWrapper = (attrResolved) => parent.PostResolveHook(attrResolved, parameter, parent._nameResolver);
                }

                var cloner = new AttributeCloner <TAttribute>(attributeSource, context.BindingDataContract, parent._nameResolver, hookWrapper);

                Func <object, object> buildFromAttribute;
                FuncConverter <TType, TAttribute, TUserType> converter = null;

                // Prefer the shortest route to creating the user type.
                // If TType matches the user type directly, then we should be able to directly invoke the builder in a single step.
                //   TAttribute --> TUserType
                var checker = ConverterManager.GetTypeValidator <TType>();

                if (checker.IsMatch(typeof(TUserType)))
                {
                    buildFromAttribute = patternMatcher.TryGetConverterFunc(typeof(TAttribute), typeof(TUserType));
                }
                else
                {
                    // Try with a converter
                    // Find a builder for :   TAttribute --> TType
                    // and then couple with a converter:  TType --> TParameterType
                    converter = cm.GetConverter <TType, TUserType, TAttribute>();
                    if (converter == null)
                    {
                        return(null);
                    }

                    buildFromAttribute = patternMatcher.TryGetConverterFunc(typeof(TAttribute), typeof(TType));
                }

                if (buildFromAttribute == null)
                {
                    return(null);
                }

                ParameterDescriptor param;

                if (parent.BuildParameterDescriptor != null)
                {
                    param = parent.BuildParameterDescriptor(attributeSource, parameter, parent._nameResolver);
                }
                else
                {
                    param = new ParameterDescriptor
                    {
                        Name         = parameter.Name,
                        DisplayHints = new ParameterDisplayHints
                        {
                            Description = "input"
                        }
                    };
                }

                return(new ExactBinding <TUserType>(cloner, param, buildFromAttribute, converter));
            }