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