public XlParameterInfo ReturnType; // Macro will have ReturnType null (as will native async functions) // THROWS: Throws a DnaMarshalException if the method cannot be turned into an XlMethodInfo // TODO: Manage errors if things go wrong XlMethodInfo(MethodInfo targetMethod, object target, LambdaExpression lambdaExpression, object methodAttribute, List <object> argumentAttributes) { if ((targetMethod == null && lambdaExpression == null) || (targetMethod != null && lambdaExpression != null) || (target != null && targetMethod == null)) { throw new ArgumentException("Invalid arguments for XlMarshalInfo"); } MethodInfo = targetMethod; Target = target; LambdaExpression = lambdaExpression; // Default Name, Description and Category Name = targetMethod?.Name ?? lambdaExpression.Name; Description = ""; Category = ExcelIntegration.DnaLibraryGetName(); HelpTopic = ""; IsVolatile = false; IsExceptionSafe = false; IsHidden = false; IsMacroType = false; IsThreadSafe = false; IsClusterSafe = false; ExplicitRegistration = false; ShortCut = ""; // DOCUMENT: Default MenuName is the library name // but menu is only added if at least the MenuText is set. MenuName = Category; MenuText = null; // Menu is only // Set default IsCommand - overridden by having an [ExcelCommand] or [ExcelFunction] attribute, // or by being a native async function. // (Must be done before SetAttributeInfo) var returnType = targetMethod?.ReturnType ?? lambdaExpression.ReturnType; IsCommand = (returnType == typeof(void)); SetAttributeInfo(methodAttribute); // We shortcut the rest of the registration if (ExplicitRegistration) { return; } FixHelpTopic(); // Return type conversion // Careful here - native async functions also return void if (returnType == typeof(void)) { ReturnType = null; } else { ReturnType = new XlParameterInfo(returnType, true, IsExceptionSafe); } if (targetMethod != null) { ParameterInfo[] parameters = targetMethod.GetParameters(); // Parameters - meta-data and type conversion Parameters = new XlParameterInfo[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { object argAttrib = null; if (argumentAttributes != null && i < argumentAttributes.Count) { argAttrib = argumentAttributes[i]; } var param = parameters[i]; Parameters[i] = new XlParameterInfo(param.Name, param.ParameterType, argAttrib); } } else { var parameters = lambdaExpression.Parameters; // Parameters - meta-data and type conversion Parameters = new XlParameterInfo[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { object argAttrib = null; if (argumentAttributes != null && i < argumentAttributes.Count) { argAttrib = argumentAttributes[i]; } var param = parameters[i]; Parameters[i] = new XlParameterInfo(param.Name, param.Type, argAttrib); } } // A native async function might still be marked as a command - check and fix. // (these have the ExcelAsyncHandle as last parameter) // (This check needs the Parameters array to be set up already.) if (IsExcelAsyncFunction) { // It really is a function, though it might return null IsCommand = false; } }