From a649db2c2429b4ec10e252607ffa8cf0184d8a62 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sat, 26 Jul 2025 17:39:03 +0500 Subject: [PATCH 1/7] Added a dynamic standard function registration test. --- .../ExcelDna.AddIn.RuntimeTests/AddIn.cs | 16 +++++++++++++ .../DynamicFunctions.cs | 23 +++++++++++++++++++ .../ExcelDna.RuntimeTests/Registration.cs | 8 +++++++ 3 files changed, 47 insertions(+) create mode 100644 Source/Tests/ExcelDna.AddIn.RuntimeTests/AddIn.cs create mode 100644 Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs diff --git a/Source/Tests/ExcelDna.AddIn.RuntimeTests/AddIn.cs b/Source/Tests/ExcelDna.AddIn.RuntimeTests/AddIn.cs new file mode 100644 index 00000000..05891e16 --- /dev/null +++ b/Source/Tests/ExcelDna.AddIn.RuntimeTests/AddIn.cs @@ -0,0 +1,16 @@ +using ExcelDna.Integration; + +namespace ExcelDna.AddIn.RuntimeTests +{ + public class AddIn : IExcelAddIn + { + public void AutoOpen() + { + DynamicFunctions.Register(); + } + + public void AutoClose() + { + } + } +} diff --git a/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs b/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs new file mode 100644 index 00000000..00bd3ae3 --- /dev/null +++ b/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs @@ -0,0 +1,23 @@ +using ExcelDna.Registration; + +namespace ExcelDna.AddIn.RuntimeTests +{ + internal class DynamicFunctions + { + public static void Register() + { + ExcelFunctionRegistration[] functions = { CreateRegistration(nameof(DynamicSayHello)) }; + ExcelRegistration.RegisterFunctions(functions); + } + + private static string DynamicSayHello(string name) + { + return $"Dynamic Hello {name}"; + } + + private static ExcelFunctionRegistration CreateRegistration(string name) + { + return new ExcelFunctionRegistration(typeof(DynamicFunctions).GetMethod(name, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)); + } + } +} diff --git a/Source/Tests/ExcelDna.RuntimeTests/Registration.cs b/Source/Tests/ExcelDna.RuntimeTests/Registration.cs index 2bd7e4c7..c2e3d9b3 100644 --- a/Source/Tests/ExcelDna.RuntimeTests/Registration.cs +++ b/Source/Tests/ExcelDna.RuntimeTests/Registration.cs @@ -625,5 +625,13 @@ public void Params() Assert.Equal("5//4//3", functionRange.Value.ToString()); } } + + [ExcelFact(Workbook = "", AddIn = AddInPath.RuntimeTests)] + public void DynamicFunctions() + { + Range functionRange = ((Worksheet)ExcelDna.Testing.Util.Workbook.Sheets[1]).Range["B1:B1"]; + functionRange.Formula = "=DynamicSayHello(\"world\")"; + Assert.Equal("Dynamic Hello world", functionRange.Value.ToString()); + } } } From 693a2560f252a053bb9b03792d24e36221f3b3cb Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sun, 27 Jul 2025 12:04:35 +0500 Subject: [PATCH 2/7] Removed unused variable. --- Source/ExcelDna.Integration/AssemblyLoader.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/ExcelDna.Integration/AssemblyLoader.cs b/Source/ExcelDna.Integration/AssemblyLoader.cs index 2677178e..adacc34d 100644 --- a/Source/ExcelDna.Integration/AssemblyLoader.cs +++ b/Source/ExcelDna.Integration/AssemblyLoader.cs @@ -36,8 +36,6 @@ public static void ProcessAssemblies( List rtdServerTypes, List comClassTypes) { - bool loadRibbons = true; - foreach (ExportedAssembly assembly in assemblies) { int initialObjectsCount = methods.Count + From 2ea7b3d9357b3ec4f3d528ae335c6d073db6bf8f Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sun, 27 Jul 2025 12:06:58 +0500 Subject: [PATCH 3/7] Fixed repetitive async function registration processing. --- Source/ExcelDna.Integration/ExcelAttributes.cs | 16 ++++++++++++++++ .../Registration/AsyncRegistration.cs | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Source/ExcelDna.Integration/ExcelAttributes.cs b/Source/ExcelDna.Integration/ExcelAttributes.cs index b729ef5a..1806d920 100644 --- a/Source/ExcelDna.Integration/ExcelAttributes.cs +++ b/Source/ExcelDna.Integration/ExcelAttributes.cs @@ -38,6 +38,22 @@ public ExcelFunctionAttribute(string description) { Description = description; } + + public ExcelFunctionAttribute(ExcelFunctionAttribute src) + { + Category = src.Category; + Name = src.Name; + Description = src.Description; + HelpTopic = src.HelpTopic; + IsVolatile = src.IsVolatile; + IsHidden = src.IsHidden; + IsExceptionSafe = src.IsExceptionSafe; + IsMacroType = src.IsMacroType; + IsThreadSafe = src.IsThreadSafe; + IsClusterSafe = src.IsClusterSafe; + ExplicitRegistration = src.ExplicitRegistration; + SuppressOverwriteError = src.SuppressOverwriteError; + } } /// diff --git a/Source/ExcelDna.Integration/Registration/AsyncRegistration.cs b/Source/ExcelDna.Integration/Registration/AsyncRegistration.cs index f9057a58..ff304661 100644 --- a/Source/ExcelDna.Integration/Registration/AsyncRegistration.cs +++ b/Source/ExcelDna.Integration/Registration/AsyncRegistration.cs @@ -43,7 +43,7 @@ public static class AsyncRegistration ParameterConversionRegistration.ApplyParameterConversions(reg, ObjectHandleRegistration.GetParameterConversionConfiguration()); reg.FunctionLambda = WrapMethodObservable(reg.FunctionLambda, reg.Return.CustomAttributes); } - else if (ReturnsTask(reg.FunctionLambda) || reg.FunctionAttribute is ExcelDna.Registration.ExcelAsyncFunctionAttribute) + else if (ReturnsTask(reg.FunctionLambda) || reg.FunctionAttribute is ExcelAsyncFunctionAttribute) { ParameterConversionRegistration.ApplyParameterConversions(reg, ObjectHandleRegistration.GetParameterConversionConfiguration()); if (HasCancellationToken(reg.FunctionLambda)) @@ -58,6 +58,9 @@ public static class AsyncRegistration reg.FunctionLambda = useNativeAsync ? WrapMethodNativeAsyncTask(reg.FunctionLambda) : WrapMethodRunTask(reg.FunctionLambda, reg.Return.CustomAttributes); } + + if (reg.FunctionAttribute is ExcelAsyncFunctionAttribute) + reg.FunctionAttribute = new ExcelFunctionAttribute(reg.FunctionAttribute); } // else do nothing to this registration } From a908346932cc7a00b9f4d96d33700a0121b80ce4 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sun, 27 Jul 2025 12:29:10 +0500 Subject: [PATCH 4/7] Added extended registration for explicit/dynamic functions. --- Source/ExcelDna.Integration/DnaLibrary.cs | 27 +++++++---- .../ExtendedRegistration/Registration.cs | 47 ++++++++++++------- .../Registration/ExcelRegistration.cs | 14 ++++-- .../DynamicFunctions.cs | 13 ++++- .../ExcelDna.RuntimeTests/Registration.cs | 13 +++-- 5 files changed, 79 insertions(+), 35 deletions(-) diff --git a/Source/ExcelDna.Integration/DnaLibrary.cs b/Source/ExcelDna.Integration/DnaLibrary.cs index 0919e231..771b8b13 100644 --- a/Source/ExcelDna.Integration/DnaLibrary.cs +++ b/Source/ExcelDna.Integration/DnaLibrary.cs @@ -257,16 +257,10 @@ internal List GetAssemblies(string pathResolveRoot) [XmlIgnore] private List _methods = new List(); [XmlIgnore] - List _excelParameterConversions = new List(); - [XmlIgnore] - List _excelReturnConversions = new List(); + private ExtendedRegistration.Registration.Configuration _extendedRegistrationConfiguration; [XmlIgnore] private List _excelFunctionsExtendedRegistration = new List(); [XmlIgnore] - private List _excelFunctionExecutionHandlerSelectors = new List(); - [XmlIgnore] - private List _excelFunctionProcessors = new List(); - [XmlIgnore] private List _exportedAssemblies; // The idea is that Initialize compiles, loads and sorts out the assemblies, @@ -283,7 +277,14 @@ internal void Initialize() // Recursively get assemblies down .dna tree. _exportedAssemblies = GetAssemblies(dnaResolveRoot); - AssemblyLoader.ProcessAssemblies(_exportedAssemblies, _methods, _excelParameterConversions, _excelReturnConversions, _excelFunctionProcessors, _excelFunctionsExtendedRegistration, _excelFunctionExecutionHandlerSelectors, _addIns, rtdServerTypes, comClassTypes); + + var excelParameterConversions = new List(); + var excelReturnConversions = new List(); + var excelFunctionExecutionHandlerSelectors = new List(); + var excelFunctionProcessors = new List(); + AssemblyLoader.ProcessAssemblies(_exportedAssemblies, _methods, excelParameterConversions, excelReturnConversions, excelFunctionProcessors, _excelFunctionsExtendedRegistration, excelFunctionExecutionHandlerSelectors, _addIns, rtdServerTypes, comClassTypes); + _extendedRegistrationConfiguration = new ExtendedRegistration.Registration.Configuration() { ParameterConversions = excelParameterConversions, ReturnConversions = excelReturnConversions, ExcelFunctionProcessors = excelFunctionProcessors, ExcelFunctionExecutionHandlerSelectors = excelFunctionExecutionHandlerSelectors }; + NativeAOT.ExcelAddIns.ForEach(i => AssemblyLoader.GetExcelAddIns(null, i, _addIns)); // Register RTD Server Types (i.e. remember that these types are available as RTD servers, with relevant ProgId etc.) @@ -330,7 +331,7 @@ internal void AutoOpen() // Register my Methods var allMethods = _methods.Select(i => new Registration.ExcelFunctionRegistration(i)).Concat(_excelFunctionsExtendedRegistration); - ExtendedRegistration.Registration.RegisterExtended(allMethods, _excelParameterConversions, _excelReturnConversions, _excelFunctionProcessors, _excelFunctionExecutionHandlerSelectors); + ExtendedRegistration.Registration.Register(allMethods, _extendedRegistrationConfiguration); // Invoke AutoOpen in all assemblies foreach (AssemblyLoader.ExcelAddInInfo addIn in _addIns) @@ -621,6 +622,14 @@ internal static string ExecutingDirectory } } + internal static ExtendedRegistration.Registration.Configuration ExtendedRegistrationConfiguration + { + get + { + return CurrentLibrary._extendedRegistrationConfiguration; + } + } + public string ResolvePath(string path) { return ResolvePath(path, dnaResolveRoot); diff --git a/Source/ExcelDna.Integration/ExtendedRegistration/Registration.cs b/Source/ExcelDna.Integration/ExtendedRegistration/Registration.cs index a14dcc23..c17e30ad 100644 --- a/Source/ExcelDna.Integration/ExtendedRegistration/Registration.cs +++ b/Source/ExcelDna.Integration/ExtendedRegistration/Registration.cs @@ -10,35 +10,48 @@ namespace ExcelDna.Integration.ExtendedRegistration { internal class Registration { - public static void RegisterExtended(IEnumerable functions, IEnumerable parameterConversions, IEnumerable returnConversions, IEnumerable excelFunctionProcessors, IEnumerable excelFunctionExecutionHandlerSelectors) + public class Configuration + { + public IEnumerable ParameterConversions { get; set; } + public IEnumerable ReturnConversions { get; set; } + public IEnumerable ExcelFunctionProcessors { get; set; } + public IEnumerable ExcelFunctionExecutionHandlerSelectors { get; set; } + } + + public static void Register(IEnumerable functions, Configuration configuration) + { + Register(Process(functions, configuration)); + } + + public static void Register(IEnumerable functions) + { + functions = functions.ToList(); + var lambdas = functions.Select(reg => reg.FunctionLambda).ToList(); + var attribs = functions.Select(reg => reg.FunctionAttribute).ToList(); + var argAttribs = functions.Select(reg => reg.ParameterRegistrations.Select(pr => pr.ArgumentAttribute).ToList()).ToList(); + ExcelIntegration.RegisterLambdaExpressions(lambdas, attribs, argAttribs); + } + + public static IEnumerable Process(IEnumerable functions, Configuration configuration) { // Set the Parameter Conversions before they are applied by the ProcessParameterConversions call below. // CONSIDER: We might change the registration to be an object...? - var conversionConfig = GetParameterConversionConfig(parameterConversions, returnConversions); + var conversionConfig = GetParameterConversionConfig(configuration.ParameterConversions, configuration.ReturnConversions); - var functionHandlerConfig = GetFunctionExecutionHandlerConfig(excelFunctionExecutionHandlerSelectors); + var functionHandlerConfig = GetFunctionExecutionHandlerConfig(configuration.ExcelFunctionExecutionHandlerSelectors); - Register(functions + return functions .UpdateRegistrationsForRangeParameters() - .ProcessFunctionProcessors(excelFunctionProcessors, conversionConfig) + .ProcessFunctionProcessors(configuration.ExcelFunctionProcessors, conversionConfig) .ProcessParameterConversions(conversionConfig) .ProcessAsyncRegistrations(nativeAsyncIfAvailable: false) .ProcessParamsRegistrations() .ProcessObjectHandles() .ProcessFunctionExecutionHandlers(functionHandlerConfig) - ); - } - - internal static void Register(IEnumerable functions) - { - functions = functions.ToList(); - var lambdas = functions.Select(reg => reg.FunctionLambda).ToList(); - var attribs = functions.Select(reg => reg.FunctionAttribute).ToList(); - var argAttribs = functions.Select(reg => reg.ParameterRegistrations.Select(pr => pr.ArgumentAttribute).ToList()).ToList(); - ExcelIntegration.RegisterLambdaExpressions(lambdas, attribs, argAttribs); + ; } - static ParameterConversionConfiguration GetParameterConversionConfig(IEnumerable parameterConversions, IEnumerable returnConversions) + private static ParameterConversionConfiguration GetParameterConversionConfig(IEnumerable parameterConversions, IEnumerable returnConversions) { // NOTE: The parameter conversion list is processed once per parameter. // Parameter conversions will apply from most inside, to most outside. @@ -93,7 +106,7 @@ static ParameterConversionConfiguration GetParameterConversionConfig(IEnumerable return paramConversionConfig; } - static FunctionExecutionConfiguration GetFunctionExecutionHandlerConfig(IEnumerable excelFunctionExecutionHandlerSelectors) + private static FunctionExecutionConfiguration GetFunctionExecutionHandlerConfig(IEnumerable excelFunctionExecutionHandlerSelectors) { FunctionExecutionConfiguration result = new FunctionExecutionConfiguration(); diff --git a/Source/ExcelDna.Integration/Registration/ExcelRegistration.cs b/Source/ExcelDna.Integration/Registration/ExcelRegistration.cs index b2e8de24..b4adbb6f 100644 --- a/Source/ExcelDna.Integration/Registration/ExcelRegistration.cs +++ b/Source/ExcelDna.Integration/Registration/ExcelRegistration.cs @@ -1,10 +1,7 @@ using ExcelDna.Integration; -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Text; -using System.Threading.Tasks; namespace ExcelDna.Registration { @@ -33,13 +30,22 @@ where mi.GetCustomAttribute() != null select new ExcelFunctionRegistration(mi); } + /// + /// Prepares the given functions for registration with Excel-DNA. + /// + /// + public static IEnumerable ProcessFunctions(this IEnumerable registrationEntries) + { + return Integration.ExtendedRegistration.Registration.Process(registrationEntries, DnaLibrary.ExtendedRegistrationConfiguration); + } + /// /// Registers the given functions with Excel-DNA. /// /// public static void RegisterFunctions(this IEnumerable registrationEntries) { - ExcelDna.Integration.ExtendedRegistration.Registration.Register(registrationEntries); + Integration.ExtendedRegistration.Registration.Register(registrationEntries); } /// diff --git a/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs b/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs index 00bd3ae3..63821d97 100644 --- a/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs +++ b/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs @@ -6,8 +6,12 @@ internal class DynamicFunctions { public static void Register() { - ExcelFunctionRegistration[] functions = { CreateRegistration(nameof(DynamicSayHello)) }; - ExcelRegistration.RegisterFunctions(functions); + ExcelFunctionRegistration[] functions = { + CreateRegistration(nameof(DynamicSayHello)), + CreateRegistration(nameof(DynamicOptionalDouble)), + }; + + ExcelRegistration.RegisterFunctions(ExcelRegistration.ProcessFunctions(functions)); } private static string DynamicSayHello(string name) @@ -15,6 +19,11 @@ private static string DynamicSayHello(string name) return $"Dynamic Hello {name}"; } + private static string DynamicOptionalDouble(double d = 4.56) + { + return "Dynamic Optional VAL: " + d.ToString(); + } + private static ExcelFunctionRegistration CreateRegistration(string name) { return new ExcelFunctionRegistration(typeof(DynamicFunctions).GetMethod(name, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)); diff --git a/Source/Tests/ExcelDna.RuntimeTests/Registration.cs b/Source/Tests/ExcelDna.RuntimeTests/Registration.cs index c2e3d9b3..ac090851 100644 --- a/Source/Tests/ExcelDna.RuntimeTests/Registration.cs +++ b/Source/Tests/ExcelDna.RuntimeTests/Registration.cs @@ -629,9 +629,16 @@ public void Params() [ExcelFact(Workbook = "", AddIn = AddInPath.RuntimeTests)] public void DynamicFunctions() { - Range functionRange = ((Worksheet)ExcelDna.Testing.Util.Workbook.Sheets[1]).Range["B1:B1"]; - functionRange.Formula = "=DynamicSayHello(\"world\")"; - Assert.Equal("Dynamic Hello world", functionRange.Value.ToString()); + { + Range functionRange = ((Worksheet)ExcelDna.Testing.Util.Workbook.Sheets[1]).Range["B1"]; + functionRange.Formula = "=DynamicSayHello(\"world\")"; + Assert.Equal("Dynamic Hello world", functionRange.Value.ToString()); + } + { + Range functionRange = ((Worksheet)ExcelDna.Testing.Util.Workbook.Sheets[1]).Range["C1"]; + functionRange.Formula = "=DynamicOptionalDouble()"; + Assert.Equal("Dynamic Optional VAL: 4.56", functionRange.Value.ToString()); + } } } } From 8bffa8ff38f618190d2844b3c305902c354ce052 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sun, 27 Jul 2025 12:56:22 +0500 Subject: [PATCH 5/7] Disabled local nullable compilation warnings. --- .../ExcelDna.AddIn.RuntimeTests/MapArrayFunctionRegistration.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Tests/ExcelDna.AddIn.RuntimeTests/MapArrayFunctionRegistration.cs b/Source/Tests/ExcelDna.AddIn.RuntimeTests/MapArrayFunctionRegistration.cs index 48320cd4..fcf85bf2 100644 --- a/Source/Tests/ExcelDna.AddIn.RuntimeTests/MapArrayFunctionRegistration.cs +++ b/Source/Tests/ExcelDna.AddIn.RuntimeTests/MapArrayFunctionRegistration.cs @@ -7,6 +7,8 @@ using System.Linq.Expressions; using System.Reflection; +#nullable disable + namespace ExcelDna.AddIn.RuntimeTests { /// From e42dc94bb6529f6a637e777f64cc39c7187ccc5d Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sun, 27 Jul 2025 12:59:18 +0500 Subject: [PATCH 6/7] Added function registration modification test. --- .../ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs | 12 ++++++++++++ Source/Tests/ExcelDna.RuntimeTests/Registration.cs | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs b/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs index 63821d97..ed618e54 100644 --- a/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs +++ b/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs @@ -9,6 +9,7 @@ public static void Register() ExcelFunctionRegistration[] functions = { CreateRegistration(nameof(DynamicSayHello)), CreateRegistration(nameof(DynamicOptionalDouble)), + ChangeName(CreateRegistration(nameof(ChangeMe)), "DynamicFunctionName"), }; ExcelRegistration.RegisterFunctions(ExcelRegistration.ProcessFunctions(functions)); @@ -24,6 +25,17 @@ private static string DynamicOptionalDouble(double d = 4.56) return "Dynamic Optional VAL: " + d.ToString(); } + private static string ChangeMe() + { + return $"Function {nameof(ChangeMe)}"; + } + + private static ExcelFunctionRegistration ChangeName(ExcelFunctionRegistration reg, string name) + { + reg.FunctionAttribute.Name = name; + return reg; + } + private static ExcelFunctionRegistration CreateRegistration(string name) { return new ExcelFunctionRegistration(typeof(DynamicFunctions).GetMethod(name, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)); diff --git a/Source/Tests/ExcelDna.RuntimeTests/Registration.cs b/Source/Tests/ExcelDna.RuntimeTests/Registration.cs index ac090851..3fa3b989 100644 --- a/Source/Tests/ExcelDna.RuntimeTests/Registration.cs +++ b/Source/Tests/ExcelDna.RuntimeTests/Registration.cs @@ -639,6 +639,12 @@ public void DynamicFunctions() functionRange.Formula = "=DynamicOptionalDouble()"; Assert.Equal("Dynamic Optional VAL: 4.56", functionRange.Value.ToString()); } + + { + Range functionRange = ((Worksheet)ExcelDna.Testing.Util.Workbook.Sheets[1]).Range["D1"]; + functionRange.Formula = "=DynamicFunctionName()"; + Assert.Equal("Function ChangeMe", functionRange.Value.ToString()); + } } } } From a51c653d50a1e675a94819e281006beb428ef5c2 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sun, 27 Jul 2025 13:25:50 +0500 Subject: [PATCH 7/7] Added a test for dynamic function registration without processing. --- .../DynamicFunctions.cs | 21 +++++++++++++------ .../ExcelDna.RuntimeTests/Registration.cs | 6 +++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs b/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs index ed618e54..caa94edb 100644 --- a/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs +++ b/Source/Tests/ExcelDna.AddIn.RuntimeTests/DynamicFunctions.cs @@ -6,13 +6,22 @@ internal class DynamicFunctions { public static void Register() { - ExcelFunctionRegistration[] functions = { - CreateRegistration(nameof(DynamicSayHello)), - CreateRegistration(nameof(DynamicOptionalDouble)), - ChangeName(CreateRegistration(nameof(ChangeMe)), "DynamicFunctionName"), - }; + { + ExcelFunctionRegistration[] functions = { + CreateRegistration(nameof(DynamicSayHello)), + CreateRegistration(nameof(DynamicOptionalDouble)), + ChangeName(CreateRegistration(nameof(ChangeMe)), "DynamicFunctionName"), + }; - ExcelRegistration.RegisterFunctions(ExcelRegistration.ProcessFunctions(functions)); + ExcelRegistration.RegisterFunctions(ExcelRegistration.ProcessFunctions(functions)); + } + { + ExcelFunctionRegistration[] functions = { + ChangeName(CreateRegistration(nameof(DynamicOptionalDouble)), "DynamicOptionalDoubleUnprocessed"), + }; + + ExcelRegistration.RegisterFunctions(functions); + } } private static string DynamicSayHello(string name) diff --git a/Source/Tests/ExcelDna.RuntimeTests/Registration.cs b/Source/Tests/ExcelDna.RuntimeTests/Registration.cs index 3fa3b989..f34a4ef8 100644 --- a/Source/Tests/ExcelDna.RuntimeTests/Registration.cs +++ b/Source/Tests/ExcelDna.RuntimeTests/Registration.cs @@ -639,12 +639,16 @@ public void DynamicFunctions() functionRange.Formula = "=DynamicOptionalDouble()"; Assert.Equal("Dynamic Optional VAL: 4.56", functionRange.Value.ToString()); } - { Range functionRange = ((Worksheet)ExcelDna.Testing.Util.Workbook.Sheets[1]).Range["D1"]; functionRange.Formula = "=DynamicFunctionName()"; Assert.Equal("Function ChangeMe", functionRange.Value.ToString()); } + { + Range functionRange = ((Worksheet)ExcelDna.Testing.Util.Workbook.Sheets[1]).Range["E1"]; + functionRange.Formula = "=DynamicOptionalDoubleUnprocessed()"; + Assert.Equal("Dynamic Optional VAL: 0", functionRange.Value.ToString()); + } } } }