public static void GetParameters(this MethodInfo mi, int ignoreCount,
                                         out ManagementParamAttribute[] attributes, out DataType[] paramTypes)
        {
            ParameterInfo[] paramInfos = mi.GetParameters();
            int             count      = paramInfos.Length - ignoreCount;

            attributes = new ManagementParamAttribute[count];
            paramTypes = new DataType[count];
            for (int i = 0; i < count; i++)
            {
                if (paramInfos[i].ParameterType.IsGenericParameter)
                {
                    throw new NotSupportedException("Generic parameter not supported for " + paramInfos[i].Name);
                }

                var paramAttribute = paramInfos[i].GetCustomAttribute <ManagementParamAttribute>();
                if (paramAttribute == null)
                {
                    paramAttribute = new ManagementParamAttribute();
                }

                if (paramAttribute.Name == null)
                {
                    paramAttribute.Name = paramInfos[i].Name;
                }

                attributes[i] = paramAttribute;
                paramTypes[i] = DataType.Wrap(paramInfos[i].ParameterType);
            }
        }
            public async Task <object> Start()
            {
                RequestResponseAmqpLink requestLink = await this.client.link.GetOrCreateAsync(TimeSpan.FromMinutes(1));

                ApplicationProperties properties = new ApplicationProperties();

                properties.Map[AmqpClientConstants.ManagementOperationKey] = this.md.Operation.Name;
                // generate message sections containing the arguments
                // convert custom-type parameters if needed
                object  bodyValue = null;
                AmqpMap bodyMap   = null;

                for (int i = 0; i < this.argCount; i++)
                {
                    ManagementParamAttribute paramAttribute = this.md.Parameters[i];
                    object value = SerializationHelper.ToAmqp(this.md.ParameterTypes[i].Serializable, this.mcm.InArgs[i]);

                    if (paramAttribute.Location == ManagementParamLocation.ApplicationProperties)
                    {
                        properties.Map[paramAttribute.Name] = value;
                    }
                    else if (paramAttribute.Location == ManagementParamLocation.MapBody)
                    {
                        if (bodyMap == null)
                        {
                            bodyMap = new AmqpMap();
                        }

                        bodyMap[new MapKey(paramAttribute.Name)] = value;
                    }
                    else
                    {
                        bodyValue = value;
                    }
                }

                // Upsert link RequestProperties to ApplicationProperties
                foreach (var requestProperty in requestLink.RequestProperties)
                {
                    properties.Map[requestProperty.Key] = requestProperty.Value;
                }

                this.request = AmqpMessage.Create(new AmqpValue {
                    Value = bodyMap ?? bodyValue
                });
                this.request.ApplicationProperties = properties;

                this.response = await requestLink.RequestAsync(request, TimeSpan.FromMinutes(1));

                int    statusCode        = (int)this.response.ApplicationProperties.Map[AmqpClientConstants.ResponseStatusCode];
                string statusDescription = (string)this.response.ApplicationProperties.Map[AmqpClientConstants.ResponseStatusDescription];

                if (statusCode != (int)AmqpResponseStatusCode.Accepted && statusCode != (int)AmqpResponseStatusCode.OK)
                {
                    AmqpSymbol errorCondition = AmqpExceptionHelper.GetResponseErrorCondition(this.response, (AmqpResponseStatusCode)statusCode);
                    Error      error          = new Error {
                        Condition = errorCondition, Description = statusDescription
                    };
                    throw new AmqpException(error);
                }

                object returnValue = null;

                if (this.response.ValueBody != null)
                {
                    returnValue = this.response.ValueBody.Value;
                }

                if (md.ReturnType.HasValue && returnValue != null)
                {
                    Type             expected     = md.ReturnType.Type;
                    SerializableType serializable = md.ReturnType.Serializable;
                    if (serializable == null)
                    {
                        // must be a generic parameter
                        expected     = mcm.GenericTypes[md.ReturnType.Type.GenericParameterPosition];
                        serializable = expected.GetSerializable();
                    }

                    returnValue = SerializationHelper.FromAmqp(serializable, returnValue);
                    if (!expected.IsAssignableFrom(returnValue.GetType()))
                    {
                        throw new InvalidOperationException($"Return type mismatch in {mcm.MethodBase.Name}. Expect {expected.Name} Actual {returnValue.GetType().Name}");
                    }
                }

                return(returnValue);
            }