Exemple #1
0
        public Task <IBinding> TryCreateAsync(BindingProviderContext context)
        {
            IReadOnlyDictionary <string, Type> bindingDataContract = context.BindingDataContract;
            string parameterName = context.Parameter.Name;

            if (bindingDataContract == null || !bindingDataContract.ContainsKey(parameterName))
            {
                return(Task.FromResult <IBinding>(null));
            }

            Type bindingDataType = bindingDataContract[parameterName];

            if (bindingDataType.IsByRef)
            {
                return(Task.FromResult <IBinding>(null));
            }

            if (bindingDataType.ContainsGenericParameters)
            {
                return(Task.FromResult <IBinding>(null));
            }

            IBindingProvider typedProvider = CreateTypedBindingProvider(bindingDataType);

            return(typedProvider.TryCreateAsync(context));
        }
Exemple #2
0
        public static async Task <bool> CanBindAsync(IBindingProvider provider, Attribute attribute, Type t)
        {
            ParameterInfo parameterInfo = new FakeParameterInfo(
                t,
                new FakeMemberInfo(),
                attribute,
                null);

            BindingProviderContext bindingProviderContext = new BindingProviderContext(
                parameterInfo, bindingDataContract: null, cancellationToken: CancellationToken.None);

            try
            {
                var binding = await provider.TryCreateAsync(bindingProviderContext);
            }
            catch (Exception)
            {
                return(false);
            }
            return(true);
        }
        public Task <IBinding> TryCreateAsync(BindingProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            Type parametertype = context.Parameter.ParameterType;

            var attr = context.Parameter.GetCustomAttribute <TAttribute>();

            var cloner           = new AttributeCloner <TAttribute>(attr, context.BindingDataContract, _nameResolver);
            var attrNameResolved = cloner.GetNameResolvedAttribute();

            // This may do validation and throw too.
            bool canBind = _predicate(attrNameResolved, parametertype);

            if (!canBind)
            {
                return(Task.FromResult <IBinding>(null));
            }
            return(_inner.TryCreateAsync(context));
        }
Exemple #4
0
        public async Task <IBinding> TryCreateAsync(BindingProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            var binding = await _inner.TryCreateAsync(context);

            if (binding != null)
            {
                // Only run the validator if the inner binding claims it.
                // Expected this will throw on errors.
                Type parameterType = context.Parameter.ParameterType;
                var  attr          = context.Parameter.GetCustomAttribute <TAttribute>();

                var cloner           = new AttributeCloner <TAttribute>(attr, context.BindingDataContract, _configuration, _nameResolver);
                var attrNameResolved = cloner.GetNameResolvedAttribute();
                _validator(attrNameResolved, parameterType);
            }

            return(binding);
        }
        internal async Task IndexMethodAsyncCore(MethodInfo method, IFunctionIndexCollector index,
                                                 CancellationToken cancellationToken)
        {
            Debug.Assert(method != null);
            bool hasNoAutomaticTrigger = method.GetCustomAttribute <NoAutomaticTriggerAttribute>() != null;

            ITriggerBinding triggerBinding   = null;
            ParameterInfo   triggerParameter = null;

            ParameterInfo[] parameters = method.GetParameters();

            foreach (ParameterInfo parameter in parameters)
            {
                ITriggerBinding possibleTriggerBinding = await _triggerBindingProvider.TryCreateAsync(
                    new TriggerBindingProviderContext(parameter, cancellationToken));

                if (possibleTriggerBinding != null)
                {
                    if (triggerBinding == null)
                    {
                        triggerBinding   = possibleTriggerBinding;
                        triggerParameter = parameter;
                    }
                    else
                    {
                        throw new InvalidOperationException("More than one trigger per function is not allowed.");
                    }
                }
            }

            Dictionary <string, IBinding>      nonTriggerBindings = new Dictionary <string, IBinding>();
            IReadOnlyDictionary <string, Type> bindingDataContract;

            if (triggerBinding != null)
            {
                bindingDataContract = triggerBinding.BindingDataContract;
            }
            else
            {
                bindingDataContract = null;
            }

            bool      hasParameterBindingAttribute  = false;
            Exception invalidInvokeBindingException = null;

            foreach (ParameterInfo parameter in parameters)
            {
                if (parameter == triggerParameter)
                {
                    continue;
                }

                IBinding binding = await _bindingProvider.TryCreateAsync(new BindingProviderContext(parameter,
                                                                                                    bindingDataContract, cancellationToken));

                if (binding == null)
                {
                    if (triggerBinding != null && !hasNoAutomaticTrigger)
                    {
                        throw new InvalidOperationException("Cannot bind parameter '" + parameter.Name +
                                                            "' when using this trigger.");
                    }
                    else
                    {
                        // Host.Call-only parameter
                        string parameterName = parameter.Name;
                        Type   parameterType = parameter.ParameterType;

                        binding = InvokeBinding.Create(parameterName, parameterType);

                        if (binding == null && invalidInvokeBindingException == null)
                        {
                            // This function might not have any attribute, in which case we shouldn't throw an
                            // exception when we can't bind it. Instead, save this exception for later once we determine
                            // whether or not it is an SDK function.
                            invalidInvokeBindingException = new InvalidOperationException("Cannot bind parameter '" +
                                                                                          parameterName + "' to type " + parameterType.Name + ".");
                        }
                    }
                }
                else if (!hasParameterBindingAttribute)
                {
                    hasParameterBindingAttribute = binding.FromAttribute;
                }

                nonTriggerBindings.Add(parameter.Name, binding);
            }

            // Only index functions with some kind of attribute on them. Three ways that could happen:
            // 1. There's an attribute on a trigger parameter (all triggers come from attributes).
            // 2. There's an attribute on a non-trigger parameter (some non-trigger bindings come from attributes).
            if (triggerBinding == null && !hasParameterBindingAttribute)
            {
                // 3. There's an attribute on the method itself (NoAutomaticTrigger).
                if (method.GetCustomAttribute <NoAutomaticTriggerAttribute>() == null)
                {
                    return;
                }
            }

            Type returnType = method.ReturnType;

            if (returnType != typeof(void) && returnType != typeof(Task))
            {
                throw new InvalidOperationException("Functions must return Task or void.");
            }

            if (invalidInvokeBindingException != null)
            {
                throw invalidInvokeBindingException;
            }

            // Validation: prevent multiple ConsoleOutputs
            if (nonTriggerBindings.OfType <ConsoleOutputBinding>().Count() > 1)
            {
                throw new InvalidOperationException(
                          "Can't have multiple console output TextWriter parameters on a single function.");
            }

            string             triggerParameterName = triggerParameter != null ? triggerParameter.Name : null;
            FunctionDescriptor functionDescriptor   = CreateFunctionDescriptor(method, triggerParameterName,
                                                                               triggerBinding, nonTriggerBindings);
            IFunctionInvoker    invoker = FunctionInvokerFactory.Create(method, _activator);
            IFunctionDefinition functionDefinition;

            if (triggerBinding != null)
            {
                functionDefinition = triggerBinding.CreateFunctionDefinition(nonTriggerBindings, invoker,
                                                                             functionDescriptor);

                if (hasNoAutomaticTrigger && functionDefinition != null)
                {
                    functionDefinition = new FunctionDefinition(functionDefinition.InstanceFactory, listenerFactory: null);
                }
            }
            else
            {
                IFunctionInstanceFactory instanceFactory = new FunctionInstanceFactory(
                    new FunctionBinding(method, nonTriggerBindings), invoker, functionDescriptor);
                functionDefinition = new FunctionDefinition(instanceFactory, listenerFactory: null);
            }

            index.Add(functionDefinition, functionDescriptor, method);
        }