예제 #1
0
            private IEnumerable <IArgumentDef> GetArgsFromParameter(ParameterInfo parameterInfo, ArgumentMode argumentMode)
            {
                if (parameterInfo.ParameterType.InheritsFrom <IArgumentModel>())
                {
                    return(GetArgumentsFromModel(
                               parameterInfo.ParameterType,
                               argumentMode,
                               null,
                               value => Values[parameterInfo.Position] = value));
                }

                if (_appConfig.ParameterResolversByType.TryGetValue(parameterInfo.ParameterType, out var resolve))
                {
                    _resolvers.Add(context => Values[parameterInfo.Position] = resolve(context));
                    return(Enumerable.Empty <IArgumentDef>());
                }

                if (IsExecutionDelegate(parameterInfo))
                {
                    _nextParameterInfo = parameterInfo;
                    return(Enumerable.Empty <IArgumentDef>());
                }

                return(new ParameterArgumentDef(
                           parameterInfo,
                           GetArgumentType(parameterInfo, argumentMode),
                           _appConfig,
                           Values)
                       .ToEnumerable());
            }
예제 #2
0
    public override void OnConfigure(
        IDescriptorContext context,
        IObjectFieldDescriptor descriptor,
        MemberInfo member)
    {
        var method = (MethodInfo)member;

        if (MessageType is null)
        {
            ParameterInfo?messageParameter =
                method.GetParameters()
                .FirstOrDefault(t => t.IsDefined(typeof(EventMessageAttribute)));

            if (messageParameter is null)
            {
                throw SubscribeAttribute_MessageTypeUnspecified(member);
            }

            MessageType = messageParameter.ParameterType;
        }

        if (string.IsNullOrEmpty(With))
        {
            (string?name, string?value, Type type)topic = ResolveTopic(method);

            if (topic.value is { })
예제 #3
0
        protected void Argument(
            NameString name,
            Action <IArgumentDescriptor> argument)
        {
            if (argument is null)
            {
                throw new ArgumentNullException(nameof(argument));
            }

            name.EnsureNotEmpty(nameof(name));

            ParameterInfo?parameter = null;

            Parameters?.TryGetValue(name, out parameter);

            ArgumentDescriptor?descriptor = parameter is null
                ? Arguments.FirstOrDefault(t => t.Definition.Name.Equals(name))
                : Arguments.FirstOrDefault(t => t.Definition.Parameter == parameter);

            if (descriptor is null)
            {
                descriptor = parameter is null
                    ? ArgumentDescriptor.New(Context, name)
                    : ArgumentDescriptor.New(Context, parameter);

                Arguments.Add(descriptor);
            }

            argument(descriptor);
        }
예제 #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BoundConstructor"/> class for a successful bind.
 /// </summary>
 /// <param name="binder">The binder that generated this binding.</param>
 /// <param name="factory">The instance factory.</param>
 /// <param name="valueRetrievers">The set of value-retrieval functions.</param>
 internal BoundConstructor(ConstructorBinder binder, Func <object?[], object> factory, Func <object?>[] valueRetrievers)
 {
     CanInstantiate             = true;
     Binder                     = binder;
     _factory                   = factory ?? throw new ArgumentNullException(nameof(factory));
     _valueRetrievers           = valueRetrievers ?? throw new ArgumentNullException(nameof(valueRetrievers));
     _firstNonBindableParameter = null;
 }
예제 #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BoundConstructor"/> class, for an unsuccessful bind.
 /// </summary>
 /// <param name="binder">The binder that generated this binding.</param>
 /// <param name="firstNonBindableParameter">The first parameter that prevented binding.</param>
 internal BoundConstructor(ConstructorBinder binder, ParameterInfo firstNonBindableParameter)
 {
     Binder                     = binder;
     CanInstantiate             = false;
     _firstNonBindableParameter = firstNonBindableParameter ?? throw new ArgumentNullException(nameof(firstNonBindableParameter));
     _factory                   = null;
     _valueRetrievers           = null;
 }
예제 #6
0
 public static string?ToLoggerString(this ParameterInfo?parameterInfo, bool simpleType = false)
 {
     if (parameterInfo == null)
     {
         return(null);
     }
     return($"{{ParameterInfo: {parameterInfo.Name}, {parameterInfo.ParameterType.ToLoggerString(simpleType)}}}");
 }
예제 #7
0
        private ParameterInfo FetchReturnParameter()
        {
            if (m_returnParameter == null)
            {
                m_returnParameter = RuntimeParameterInfo.GetReturnParameter(this, this, Signature);
            }

            return(m_returnParameter);
        }
예제 #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ReflectionContext"/> class.
 /// </summary>
 /// <param name="type">Schema type.</param>
 /// <param name="propertyInfo">Optional PropertyInfo.</param>
 /// <param name="parameterInfo">Optional ParameterInfo.</param>
 public ReflectionContext(
     Type?type = null,
     MemberInfo?propertyInfo     = null,
     ParameterInfo?parameterInfo = null)
 {
     Type          = type;
     PropertyInfo  = propertyInfo;
     ParameterInfo = parameterInfo;
 }
예제 #9
0
        internal static NullHandling DetermineNullability(this ParameterInfo?parameter)
        {
            if (parameter == null)
            {
                return(NullHandling.AllowNull);
            }

            return(DetermineNullabilityImpl(parameter, parameter.CustomAttributes, parameter.Member.CustomAttributes, parameter.ParameterType.GetTypeInfo()));
        }
예제 #10
0
 public ReadOnlyArgumentDescriptor(
     Expression argument,
     ParameterInfo parameter,
     ParameterInfo methodDefinitionParameter)
 {
     _argument  = argument;
     _parameter = parameter;
     _methodDefinitionParameter = methodDefinitionParameter;
 }
예제 #11
0
        private MethodDeclarationSyntax ImplementMethod(Type type, MethodInfo method)
        {
            const string forEachVariableName = "plugIn";
            var          methodDeclaration   = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), method.Name)
                                               .AddModifiers(Token(SyntaxKind.PublicKeyword));
            var           methodCallStatement = forEachVariableName + "." + method.Name + "(";
            bool          first           = true;
            ParameterInfo?cancelEventArgs = null;

            foreach (var parameter in method.GetParameters().Where(p => !string.IsNullOrWhiteSpace(p.Name)))
            {
                methodDeclaration = methodDeclaration.AddParameterListParameters(Parameter(
                                                                                     List <AttributeListSyntax>(),
                                                                                     TokenList(),
                                                                                     ParseTypeName(this.GetTypeName(parameter.ParameterType)),
                                                                                     ParseToken(parameter.Name !),
                                                                                     null));
                if (!first)
                {
                    methodCallStatement += ", ";
                }

                methodCallStatement += parameter.Name;
                cancelEventArgs ??= parameter.ParameterType == typeof(CancelEventArgs) || parameter.ParameterType.IsSubclassOf(typeof(CancelEventArgs)) ? parameter : null;

                first = false;
            }

            methodCallStatement += ");";
            var         methodCall  = ParseStatement(methodCallStatement);
            BlockSyntax forEachBody = Block(methodCall);

            if (cancelEventArgs != null)
            {
                forEachBody = Block(IfStatement(ParseExpression("!" + cancelEventArgs.Name + ".Cancel"), forEachBody));
            }

            BlockSyntax forEachBlock = Block(
                ForEachStatement(
                    ParseTypeName(this.GetTypeName(type)),
                    forEachVariableName,
                    ParseExpression("this.ActivePlugIns"),
                    forEachBody));

            BlockSyntax methodBody = Block(
                ParseStatement("this.LockSlim.EnterReadLock();"),
                TryStatement(
                    Token(SyntaxKind.TryKeyword),
                    forEachBlock,
                    List <CatchClauseSyntax>(), // no catch clause
                    FinallyClause(
                        Block(ParseStatement("this.LockSlim.ExitReadLock();")))));

            methodDeclaration = methodDeclaration.WithBody(methodBody);
            return(methodDeclaration);
        }
            private ParameterInfo[] ParseParameterList()
            {
                // Consume the opening parenthesis or bracket
                Debug.Assert(PeekNextChar() == '(' || PeekNextChar() == '[');
                ++_index;

                char nextChar = PeekNextChar();

                if (nextChar == ')' || nextChar == ']')
                {
                    // Empty parameter list
                    ++_index;
                    return(s_noParameters);
                }

                ArrayBuilder <ParameterInfo> builder = new ArrayBuilder <ParameterInfo>();

                while (true)
                {
                    ParameterInfo?parameter = ParseParameter();
                    if (parameter != null)
                    {
                        builder.Add(parameter.Value);
                    }
                    else
                    {
                        builder.Free();
                        return(null);
                    }

                    if (PeekNextChar() == ',')
                    {
                        ++_index;
                    }
                    else
                    {
                        break;
                    }
                }

                nextChar = PeekNextChar();
                if (nextChar == ')' || nextChar == ']')
                {
                    // Consume the closing parenthesis or bracket
                    ++_index;
                }
                else
                {
                    // Malformed parameter list: missing close parenthesis or bracket
                    builder.Free();
                    return(null);
                }

                return(builder.ToArrayAndFree());
            }
 internal ArgumentDescriptor(
     IList <Expression> arguments,
     int index,
     ParameterInfo parameter,
     ParameterInfo methodDefinitionParameter)
 {
     _arguments = arguments;
     _index     = index;
     _parameter = parameter;
     _methodDefinitionParameter = methodDefinitionParameter;
 }
예제 #14
0
 /// <summary>
 /// Initializes an instance with the specified properties.
 /// </summary>
 /// <param name="memberInfo">The member being inspected.</param>
 /// <param name="isInputType">Indicates that this is an input type (an argument); false for output types.</param>
 /// <param name="type">The underlying type.</param>
 /// <param name="isNullable">Indicates that the underlying type is nullable.</param>
 /// <param name="isList">Indicates that this represents a list of elements.</param>
 /// <param name="listIsNullable">Indicates that the list is nullable.</param>
 /// <param name="graphType">The graph type of the underlying CLR type; null if not specified.</param>
 public TypeInformation(MemberInfo memberInfo, bool isInputType, Type type, bool isNullable, bool isList, bool listIsNullable, Type?graphType)
 {
     ParameterInfo  = null;
     MemberInfo     = memberInfo;
     IsInputType    = isInputType;
     Type           = type;
     IsNullable     = isNullable;
     IsList         = isList;
     ListIsNullable = listIsNullable;
     GraphType      = graphType;
 }
예제 #15
0
        internal static string GetAttributes(this IList <CustomAttributeData> @this, bool isReturn,
                                             SortedSet <string> namespaces, ParameterInfo?parameter)
        {
            Func <CustomAttributeData, bool> verify = data =>
                                                      !(parameter != null && parameter.IsOut && parameter.ParameterType.IsByRef &&
                                                        typeof(OutAttribute).IsAssignableFrom(data.AttributeType) ||
                                                        typeof(ParamArrayAttribute).IsAssignableFrom(data.AttributeType) ||
                                                        typeof(OptionalAttribute).IsAssignableFrom(data.AttributeType));

            return(@this.GetAttributes(namespaces, verify, isReturn));
        }
예제 #16
0
            public override ParameterInfo?ProjectParameter(ParameterInfo?value)
            {
                if (value == null)
                {
                    return(null);
                }

                Debug.Assert(NeedsProjection(value));

                return(new CustomParameterInfo(value, ReflectionContext));
            }
예제 #17
0
 public MergeArgType(Type?type, Type?typeWithoutPathQueryStream, string?streamPropName, TypeName?callbackAction, TypeName?cancelToken, bool hasCustomType, bool isSingleValue, ParameterInfo?singleValue, MethodInfo methodInfo)
 {
     Type                       = type;
     StreamPropName             = streamPropName;
     CallbackAction             = callbackAction;
     CancelToken                = cancelToken;
     HasCustomType              = hasCustomType;
     IsSingleValue              = isSingleValue;
     SingleValue                = singleValue;
     MethodInfo                 = methodInfo;
     TypeWithoutPathQueryStream = typeWithoutPathQueryStream;
 }
예제 #18
0
 public bool Equals(ParameterInfo?other)
 {
     if (ReferenceEquals(null, other))
     {
         return(false);
     }
     if (ReferenceEquals(this, other))
     {
         return(true);
     }
     return(Type == other.Type && FullType == other.FullType && Name == other.Name);
 }
예제 #19
0
 public bool Equals(ParameterInfo?other)
 {
     if (other == null)
     {
         return(false);
     }
     if (object.ReferenceEquals(this, other))
     {
         return(true);
     }
     return(object.Equals(Name, other.Name) &&
            Position == other.Position &&
            object.Equals(Type, other.Type));
 }
예제 #20
0
        public static (bool isSingleValue, ParameterInfo?singleValue) IsSingleCustomValue(this IList <ParameterInfo> ps)
        {
            var l = ps.ToList();

            l.RemoveAll(i => i.ParameterType.IsFuncT() || i.ParameterType.IsCancellationToken() || i.ParameterType.IsStream());
            var           ret         = l.Count == 1 && !l[0].ParameterType.IsSystemTypeOrEnum();
            ParameterInfo?singleValue = null;

            if (ret)
            {
                singleValue = l[0];
            }
            return(ret, singleValue);
        }
예제 #21
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ConstructorBinder"/> class.
        /// </summary>
        /// <param name="constructorInfo">The constructor.</param>
        public ConstructorBinder(ConstructorInfo constructorInfo)
        {
            Constructor      = constructorInfo ?? throw new ArgumentNullException(nameof(constructorInfo));
            _constructorArgs = constructorInfo.GetParameters();

            // If any of the parameters are unsafe, do not create an invoker, and store the parameter
            // that broke the rule.
            _illegalParameter = DetectIllegalParameter(_constructorArgs);

            if (_illegalParameter is null)
            {
                // Build the invoker.
                _factory = FactoryCache.GetOrAdd(constructorInfo, FactoryBuilder);
            }
        }
예제 #22
0
 public bool Equals(ParameterInfo?x, ParameterInfo?y)
 {
     if (x == null || y == null)
     {
         return(x == null && y == null);
     }
     if (x.ParameterType != y.ParameterType)
     {
         return(false);
     }
     if (x.Name != y.Name)
     {
         return(false);
     }
     return(true);
 }
예제 #23
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ConstructorParameterBinding"/> class.
        /// </summary>
        /// <param name="ci">ConstructorInfo to bind.</param>
        /// <param name="availableParameters">Available parameters.</param>
        /// <param name="context">Context in which to construct instance.</param>
        public ConstructorParameterBinding(
            ConstructorInfo ci,
            IEnumerable <Parameter> availableParameters,
            IComponentContext context)
        {
            if (ci == null)
            {
                throw new ArgumentNullException(nameof(ci));
            }
            if (availableParameters == null)
            {
                throw new ArgumentNullException(nameof(availableParameters));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            CanInstantiate = true;
            _ci            = ci;
            var parameters = ci.GetParameters();

            _valueRetrievers = new Func <object?> [parameters.Length];

            for (int i = 0; i < parameters.Length; ++i)
            {
                var  pi         = parameters[i];
                bool foundValue = false;
                foreach (var param in availableParameters)
                {
                    if (param.CanSupplyValue(pi, context, out var valueRetriever))
                    {
                        _valueRetrievers[i] = valueRetriever;
                        foundValue          = true;
                        break;
                    }
                }

                if (!foundValue)
                {
                    CanInstantiate             = false;
                    _firstNonBindableParameter = pi;
                    break;
                }
            }
        }
예제 #24
0
 /*FIXME this constructor looks very broken in the position parameter*/
 internal RuntimeParameterInfo(ParameterInfo?pinfo, Type?type, MemberInfo member, int position)
 {
     this.ClassImpl  = type;
     this.MemberImpl = member;
     if (pinfo != null)
     {
         this.NameImpl     = pinfo.Name;
         this.PositionImpl = pinfo.Position - 1; // ParameterInfo.Position is zero-based
         this.AttrsImpl    = (ParameterAttributes)pinfo.Attributes;
     }
     else
     {
         this.NameImpl     = null;
         this.PositionImpl = position - 1;
         this.AttrsImpl    = ParameterAttributes.None;
     }
 }
예제 #25
0
        private static bool InternalParamIsDefined(ParameterInfo param, Type type, bool inherit)
        {
            Debug.Assert(param != null);
            Debug.Assert(type != null);

            // For ParameterInfo's we need to make sure that we chain through all the MethodInfo's in the inheritance chain.
            // We pick up all the CustomAttributes for the starting ParameterInfo. We need to pick up only attributes
            // that are marked inherited from the remainder of the ParameterInfo's in the inheritance chain.
            // For MethodInfo's on an interface we do not do an inheritance walk. For ParameterInfo's on a
            // Class we walk up the inheritance chain but do not look at the MethodInfo's on the interfaces that the class inherits from.

            if (param.IsDefined(type, false))
            {
                return(true);
            }

            if (param.Member.DeclaringType is null || !inherit) // This is an interface so we are done.
            {
                return(false);
            }

            ParameterInfo?baseParam = GetParentDefinition(param);

            while (baseParam != null)
            {
                object[] objAttr = baseParam.GetCustomAttributes(type, false);

                for (int i = 0; i < objAttr.Length; i++)
                {
                    Type objType = objAttr[i].GetType();
                    AttributeUsageAttribute attribUsage = InternalGetAttributeUsage(objType);

                    if ((objAttr[i] is Attribute) && (attribUsage.Inherited))
                    {
                        return(true);
                    }
                }

                baseParam = GetParentDefinition(baseParam);
            }

            return(false);
        }
예제 #26
0
        private static bool IsResolverRelevant(
            Type sourceType,
            MemberInfo resolver)
        {
            if (resolver is PropertyInfo)
            {
                return(true);
            }

            if (resolver is MethodInfo m)
            {
                ParameterInfo?parent = m.GetParameters()
                                       .FirstOrDefault(t => t.IsDefined(typeof(ParentAttribute)));
                return(parent is null ||
                       parent.ParameterType.IsAssignableFrom(sourceType));
            }

            return(false);
        }
예제 #27
0
    public static BodyDescriptorInfo?ResolveBodyDescriptor(string body, Type serviceType, MethodDescriptor methodDescriptor)
    {
        if (!string.IsNullOrEmpty(body))
        {
            if (!string.Equals(body, "*", StringComparison.Ordinal))
            {
                var bodyFieldPath = body.Split('.');
                if (!TryResolveDescriptors(methodDescriptor.InputType, bodyFieldPath, out var bodyFieldDescriptors))
                {
                    throw new InvalidOperationException($"Couldn't find matching field for body '{body}' on {methodDescriptor.InputType.Name}.");
                }
                var leafDescriptor = bodyFieldDescriptors.Last();
                var propertyName   = FormatUnderscoreName(leafDescriptor.Name, pascalCase: true, preservePeriod: false);
                var propertyInfo   = leafDescriptor.ContainingType.ClrType.GetProperty(propertyName);

                if (leafDescriptor.IsRepeated)
                {
                    // A repeating field isn't a message type. The JSON parser will parse using the containing
                    // type to get the repeating collection.
                    return(new BodyDescriptorInfo(leafDescriptor.ContainingType, bodyFieldDescriptors, IsDescriptorRepeated: true, propertyInfo));
                }
                else
                {
                    return(new BodyDescriptorInfo(leafDescriptor.MessageType, bodyFieldDescriptors, IsDescriptorRepeated: false, propertyInfo));
                }
            }
            else
            {
                ParameterInfo?requestParameter = null;
                var           methodInfo       = serviceType.GetMethod(methodDescriptor.Name);
                if (methodInfo != null)
                {
                    requestParameter = methodInfo.GetParameters().SingleOrDefault(p => p.Name == "request");
                }

                return(new BodyDescriptorInfo(methodDescriptor.InputType, FieldDescriptors: null, IsDescriptorRepeated: false, ParameterInfo: requestParameter));
            }
        }

        return(null);
    }
예제 #28
0
        private static Expression BuildFactoryExpression(
            ConstructorInfo constructor,
            int?[] parameterMap,
            Expression serviceProvider,
            Expression factoryArgumentArray)
        {
            ParameterInfo[]? constructorParameters = constructor.GetParameters();
            var constructorArguments = new Expression[constructorParameters.Length];

            for (int i = 0; i < constructorParameters.Length; i++)
            {
                ParameterInfo?constructorParameter = constructorParameters[i];
                Type?         parameterType        = constructorParameter.ParameterType;
                bool          hasDefaultValue      = ParameterDefaultValue.TryGetDefaultValue(constructorParameter, out object?defaultValue);

                if (parameterMap[i] != null)
                {
                    constructorArguments[i] = Expression.ArrayAccess(factoryArgumentArray, Expression.Constant(parameterMap[i]));
                }
                else
                {
                    var parameterTypeExpression = new Expression[] { serviceProvider,
                                                                     Expression.Constant(parameterType, typeof(Type)),
                                                                     Expression.Constant(constructor.DeclaringType, typeof(Type)),
                                                                     Expression.Constant(hasDefaultValue) };
                    constructorArguments[i] = Expression.Call(GetServiceInfo, parameterTypeExpression);
                }

                // Support optional constructor arguments by passing in the default value
                // when the argument would otherwise be null.
                if (hasDefaultValue)
                {
                    ConstantExpression?defaultValueExpression = Expression.Constant(defaultValue);
                    constructorArguments[i] = Expression.Coalesce(constructorArguments[i], defaultValueExpression);
                }

                constructorArguments[i] = Expression.Convert(constructorArguments[i], parameterType);
            }

            return(Expression.New(constructor, constructorArguments));
        }
        /// <summary>
        /// Convert between types
        /// </summary>
        /// <param name="destinationType">CLR Type of destination</param>
        /// <param name="value">The value to convert</param>
        /// <returns>The converted value</returns>
        public static object?ConvertTo(Type destinationType, object value)
        {
            //NOTE: value is not null -- already been checked by caller before calling here

            if (destinationType.IsEnum && (value is string val))
            {
                // Input is a string, destination is an Enum, Enum.Parse() it to convert!
                // We are using Parse() and not TryParse() with good reason. Bad values will throw exceptions to the top-level caller
                // and we WANT that to happen!

                return(Enum.Parse(destinationType, val));
            }

            TypeConverter converter = TypeDescriptor.GetConverter(destinationType);

            if ((converter == null) || (!converter.CanConvertTo(destinationType)))
            {
                // see if type has a Parse static method
                MethodInfo[] methods = destinationType.GetMethods(BindingFlags.Public | BindingFlags.Static);
                if ((methods != null) && (methods.Length > 0))
                {
                    Type sourceType = ((value == null) ? typeof(object) : value.GetType());
                    foreach (MethodInfo m in methods)
                    {
                        if (m.Name.Equals("Parse"))
                        {
                            ParameterInfo?p = m.GetParameters()?[0];
                            if ((p != null) && (p.ParameterType == sourceType))
                            {
                                return(m.Invoke(null, new object?[] { value }));
                            }
                        }
                        else if (m.Name.Equals("TryParse"))
                        {
                            ParameterInfo?p = m.GetParameters()?[0];
                            if ((p != null) && (p.ParameterType == sourceType))
                            {
                                object?[]? parameters = new object?[] { value, null };
                                bool?      tpResult   = (bool?)m.Invoke(null, parameters);
                                return((tpResult.HasValue && tpResult.Value) ? parameters[1] : default);
예제 #30
0
        private static Attribute[] InternalParamGetCustomAttributes(ParameterInfo param, Type?type, bool inherit)
        {
            Debug.Assert(param != null);

            // For ParameterInfo's we need to make sure that we chain through all the MethodInfo's in the inheritance chain that
            // have this ParameterInfo defined. .We pick up all the CustomAttributes for the starting ParameterInfo. We need to pick up only attributes
            // that are marked inherited from the remainder of the MethodInfo's in the inheritance chain.
            // For MethodInfo's on an interface we do not do an inheritance walk so the default ParameterInfo attributes are returned.
            // For MethodInfo's on a class we walk up the inheritance chain but do not look at the MethodInfo's on the interfaces that the
            // class inherits from and return the respective ParameterInfo attributes

            List <Type> disAllowMultiple = new List <Type>();

            object?[] objAttr;

            type ??= typeof(Attribute);

            objAttr = param.GetCustomAttributes(type, false);

            for (int i = 0; i < objAttr.Length; i++)
            {
                Type objType = objAttr[i] !.GetType();
                AttributeUsageAttribute attribUsage = InternalGetAttributeUsage(objType);
                if (!attribUsage.AllowMultiple)
                {
                    disAllowMultiple.Add(objType);
                }
            }

            // Get all the attributes that have Attribute as the base class
            Attribute[] ret;
            if (objAttr.Length == 0)
            {
                ret = CreateAttributeArrayHelper(type, 0);
            }
            else
            {
                ret = (Attribute[])objAttr;
            }

            if (param.Member.DeclaringType is null) // This is an interface so we are done.
            {
                return(ret);
            }

            if (!inherit)
            {
                return(ret);
            }

            ParameterInfo?baseParam = GetParentDefinition(param);

            while (baseParam != null)
            {
                objAttr = baseParam.GetCustomAttributes(type, false);

                int count = 0;
                for (int i = 0; i < objAttr.Length; i++)
                {
                    Type objType = objAttr[i] !.GetType();
                    AttributeUsageAttribute attribUsage = InternalGetAttributeUsage(objType);

                    if ((attribUsage.Inherited) && (!disAllowMultiple.Contains(objType)))
                    {
                        if (!attribUsage.AllowMultiple)
                        {
                            disAllowMultiple.Add(objType);
                        }
                        count++;
                    }
                    else
                    {
                        objAttr[i] = null;
                    }
                }

                // Get all the attributes that have Attribute as the base class
                Attribute[] attributes = CreateAttributeArrayHelper(type, count);

                count = 0;
                for (int i = 0; i < objAttr.Length; i++)
                {
                    if (objAttr[i] is object attr)
                    {
                        attributes[count] = (Attribute)attr;
                        count++;
                    }
                }

                Attribute[] temp = ret;
                ret = CreateAttributeArrayHelper(type, temp.Length + count);
                Array.Copy(temp, ret, temp.Length);

                int offset = temp.Length;

                for (int i = 0; i < attributes.Length; i++)
                {
                    ret[offset + i] = attributes[i];
                }

                baseParam = GetParentDefinition(baseParam);
            }

            return(ret);
        }