public XlParameterInfo ReturnType; // Macro will have ReturnType null // THROWS: Throws a DnaMarshalException if the method cannot be turned into an XlMethodInfo // TODO: Manage errors if things go wrong private XlMethodInfo(MethodInfo targetMethod, ModuleBuilder modBuilder) { // Default Name, Description and Category Name = targetMethod.Name; Description = ""; Category = IntegrationHelpers.DnaLibraryGetName(); HelpTopic = ""; IsVolatile = false; IsExceptionSafe = false; IsHidden = false; IsMacroType = false; IsThreadSafe = false; ShortCut = ""; // DOCUMENT: Default MenuName is the library name // but menu is only added if at least the MenuText is set. MenuName = IntegrationHelpers.DnaLibraryGetName(); MenuText = null; // Menu is only SetAttributeInfo(targetMethod.GetCustomAttributes(false)); // Return type conversion if (targetMethod.ReturnType == typeof(void)) { IsCommand = true; ReturnType = null; // HACK: Check that there are no other parameters // Does Excel allow macros with parameters? if (targetMethod.GetParameters().Length > 0) { throw new DnaMarshalException("Macros with parameters are not supported."); } } else { IsCommand = false; ReturnType = new XlParameterInfo(targetMethod.ReturnType, true, IsExceptionSafe); } // Parameters - meta-data and type conversion Parameters = Array.ConvertAll <ParameterInfo, XlParameterInfo>( targetMethod.GetParameters(), delegate(ParameterInfo pi) { return(new XlParameterInfo(pi)); }); // Create the delegate type, wrap the targetMethod and create the delegate Type delegateType = CreateDelegateType(modBuilder); Delegate xlDelegate = CreateMethodDelegate(targetMethod, delegateType); // Need to add a reference to prevent garbage collection of our delegate // Don't need to pin, according to // "How to: Marshal Callbacks and Delegates Using C++ Interop" // Currently this delegate is never released // TODO: Clean up properly DelegateHandle = GCHandle.Alloc(xlDelegate); FunctionPointer = Marshal.GetFunctionPointerForDelegate(xlDelegate); }
internal static IntPtr XlAddInManagerInfo12(IntPtr pXloperAction12) { Debug.WriteLine("In XlAddIn.XlAddInManagerInfo12"); ICustomMarshaler m = XlObject12Marshaler.GetInstance(""); object action = m.MarshalNativeToManaged(pXloperAction12); object result; if ((action is double && (double)action == 1.0)) { InitializeIntegration(); result = IntegrationHelpers.DnaLibraryGetName(); } else { result = IntegrationMarshalHelpers.GetExcelErrorObject(IntegrationMarshalHelpers.ExcelError_ExcelErrorValue); } return(m.MarshalManagedToNative(result)); }
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(ModuleBuilder modBuilder, MethodInfo targetMethod, object target, object methodAttribute, List <object> argumentAttributes) { // Default Name, Description and Category Name = targetMethod.Name; Description = ""; Category = IntegrationHelpers.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 = IntegrationHelpers.DnaLibraryGetName(); MenuText = null; // Menu is only // Set default IsCommand - overridden by having an [ExcelCommand] attribute, // or by being a native async function. // (Must be done before SetAttributeInfo) IsCommand = (targetMethod.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 (targetMethod.ReturnType == typeof(void)) { ReturnType = null; } else { ReturnType = new XlParameterInfo(targetMethod.ReturnType, true, IsExceptionSafe); } 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]; } Parameters[i] = new XlParameterInfo(parameters[i], 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; } // Create the delegate type, wrap the targetMethod and create the delegate // CONSIDER: Currently we need a special delegate type here so that we can hook on the marshaling attributes. // Future version might do straight-forward marshaling, so we can get rid of these types (just use generic methods) // FirstArgument (if received) is not used in the delegate type created ... Type delegateType = CreateDelegateType(modBuilder); // ... but is baked into the delegate itself. Delegate xlDelegate = CreateMethodDelegate(delegateType, targetMethod, target); // Need to add a reference to prevent garbage collection of our delegate // Don't need to pin, according to // "How to: Marshal Callbacks and Delegates Using C++ Interop" // Currently this delegate is never released // TODO: Clean up properly DelegateHandle = GCHandle.Alloc(xlDelegate); FunctionPointer = Marshal.GetFunctionPointerForDelegate(xlDelegate); }
// 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, object methodAttribute, List <object> argumentAttributes) { // Default Name, Description and Category Name = targetMethod.Name; Description = ""; Category = IntegrationHelpers.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 = IntegrationHelpers.DnaLibraryGetName(); MenuText = null; // Menu is only // Set default IsCommand - overridden by having an [ExcelCommand] attribute, // or by being a native async function. // (Must be done before SetAttributeInfo) IsCommand = (targetMethod.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 (targetMethod.ReturnType == typeof(void)) { ReturnType = null; } else { ReturnType = new XlParameterInfo(targetMethod.ReturnType, true, IsExceptionSafe); } 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]; } Parameters[i] = new XlParameterInfo(parameters[i], 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; } }