/// <summary>
        /// Defined what other bindings can use and return value.
        /// </summary>
        private IReadOnlyDictionary <string, Type> CreateBindingContract(SignalRTriggerAttribute attribute, ParameterInfo parameter)
        {
            var contract = new Dictionary <string, Type>(StringComparer.OrdinalIgnoreCase)
            {
                { ReturnParameterKey, typeof(object).MakeByRefType() },
            };

            // Add names in ParameterNames to binding contract, that user can bind to Functions' parameter directly
            if (attribute.ParameterNames != null)
            {
                var parameters = ((MethodInfo)parameter.Member).GetParameters().ToDictionary(p => p.Name, p => p.ParameterType, StringComparer.OrdinalIgnoreCase);
                foreach (var parameterName in attribute.ParameterNames)
                {
                    if (parameters.ContainsKey(parameterName))
                    {
                        contract.Add(parameterName, parameters[parameterName]);
                    }
                    else
                    {
                        contract.Add(parameterName, typeof(object));
                    }
                }
            }

            return(contract);
        }
 public SignalRTriggerBinding(ParameterInfo parameterInfo, SignalRTriggerAttribute attribute, ISignalRTriggerDispatcher dispatcher)
 {
     _parameterInfo      = parameterInfo ?? throw new ArgumentNullException(nameof(parameterInfo));
     _attribute          = attribute ?? throw new ArgumentNullException(nameof(attribute));
     _dispatcher         = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
     BindingDataContract = CreateBindingContract(_attribute, _parameterInfo);
 }
Пример #3
0
        internal SignalRTriggerAttribute GetParameterResolvedAttribute(SignalRTriggerAttribute attribute, ParameterInfo parameterInfo)
        {
            //TODO: AutoResolve more properties in attribute
            var hubName                 = attribute.HubName;
            var category                = attribute.Category;
            var @event                  = attribute.Event;
            var parameterNames          = attribute.ParameterNames ?? Array.Empty <string>();
            var connectionStringSetting = attribute.ConnectionStringSetting;

            // We have two models for C#, one is function based model which also work in multiple language
            // Another one is class based model, which is highly close to SignalR itself but must keep some conventions.
            var method       = (MethodInfo)parameterInfo.Member;
            var declaredType = method.DeclaringType;

            string[] parameterNamesFromAttribute;

            if (declaredType != null && IsServerlessHub(declaredType))
            {
                // Class based model
                if (!string.IsNullOrEmpty(hubName) ||
                    !string.IsNullOrEmpty(category) ||
                    !string.IsNullOrEmpty(@event) ||
                    parameterNames.Length != 0)
                {
                    throw new ArgumentException($"{nameof(SignalRTriggerAttribute)} must use parameterless constructor in class based model.");
                }
                parameterNamesFromAttribute = method.GetParameters().Where(IsLegalClassBasedParameter).Select(p => p.Name).ToArray();
                hubName  = declaredType.Name;
                category = GetCategoryFromMethodName(method.Name);
                @event   = GetEventFromMethodName(method.Name, category);
                connectionStringSetting = declaredType.GetCustomAttribute <SignalRConnectionAttribute>()?.Connection ?? attribute.ConnectionStringSetting;
            }
            else
            {
                parameterNamesFromAttribute = method.GetParameters().
                                              Where(p => p.GetCustomAttribute <SignalRParameterAttribute>(false) != null).
                                              Select(p => p.Name).ToArray();

                if (parameterNamesFromAttribute.Length != 0 && parameterNames.Length != 0)
                {
                    throw new InvalidOperationException(
                              $"{nameof(SignalRTriggerAttribute)}.{nameof(SignalRTriggerAttribute.ParameterNames)} and {nameof(SignalRParameterAttribute)} can not be set in the same Function.");
                }

                // If we aren't using the class-based model, make sure we resolve binding expressions for attribute properties here.
                hubName  = _nameResolver.ResolveWholeString(hubName);
                category = _nameResolver.ResolveWholeString(category);
                @event   = _nameResolver.ResolveWholeString(@event);
            }

            parameterNames = parameterNamesFromAttribute.Length != 0
                ? parameterNamesFromAttribute
                : parameterNames;

            return(new SignalRTriggerAttribute(hubName, category, @event, parameterNames)
            {
                ConnectionStringSetting = connectionStringSetting
            });
        }
Пример #4
0
 private static void ValidateSignalRTriggerAttributeBinding(SignalRTriggerAttribute attribute)
 {
     if (string.IsNullOrWhiteSpace(attribute.ConnectionStringSetting))
     {
         throw new InvalidOperationException(
                   $"{nameof(SignalRTriggerAttribute)}.{nameof(SignalRConnectionInfoAttribute.ConnectionStringSetting)} is not allowed to be null or whitespace.");
     }
     ValidateParameterNames(attribute.ParameterNames);
 }
 private void ValidateSignalRTriggerAttributeBinding(SignalRTriggerAttribute attribute)
 {
     if (string.IsNullOrEmpty(attribute.ConnectionStringSetting))
     {
         throw new InvalidOperationException(string.Format(ErrorMessages.EmptyConnectionStringErrorMessageFormat,
                                                           $"{nameof(SignalRTriggerAttribute)}.{nameof(SignalRConnectionInfoAttribute.ConnectionStringSetting)}"));
     }
     ValidateParameterNames(attribute.ParameterNames);
 }
 public SignalRTriggerBinding(ParameterInfo parameterInfo, SignalRTriggerAttribute attribute, ISignalRTriggerDispatcher dispatcher, AccessKey[] accessKeys, ServiceHubContext hubContext)
 {
     _parameterInfo      = parameterInfo ?? throw new ArgumentNullException(nameof(parameterInfo));
     _attribute          = attribute ?? throw new ArgumentNullException(nameof(attribute));
     _dispatcher         = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
     _accessKeys         = accessKeys ?? throw new ArgumentNullException(nameof(accessKeys));
     _hubContext         = hubContext;
     BindingDataContract = CreateBindingContract(_attribute, _parameterInfo);
 }