Esempio 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));
            }
            public static ExactBinding <TMessage> TryBuild(
                AsyncCollectorBindingProvider <TAttribute, TType> parent,
                Mode mode,
                BindingProviderContext context)
            {
                var patternMatcher = parent._patternMatcher;

                var parameter       = context.Parameter;
                var attributeSource = TypeUtility.GetResolvedAttribute <TAttribute>(parameter);

                FuncAsyncConverter buildFromAttribute;
                FuncAsyncConverter <TMessage, 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 = OpenType.FromType <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)
                {
                    context.BindingErrors.Add(String.Format(Constants.BindingAssemblyConflictMessage, typeof(TType).AssemblyQualifiedName, typeof(TMessage).AssemblyQualifiedName));
                    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);

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