Port Lambda Boss to .NET Framework 4.8 (spec 0007)#199
Merged
Conversation
Core retargeting work for spec 0007: - All three projects target net48 - Inline Taglo.Excel.Common (Logger, NativeMethods, WindowPositioner, UpdateChecker) into addin/lambda-boss/Common/ under LambdaBoss.Common namespace; drop the PackageReference - Add PolySharp for compiler-required polyfills (IsExternalInit, Index, Range) - Add Microsoft.Bcl.HashCode for the HashCode struct - Add System.Text.Json explicit PackageReference (was framework-bundled on net6) - Add System.Net.Http + Microsoft.CSharp framework references (SDK-style net48 projects need these explicit) - Replace IReadOnlySet<T> with ISet<T> (net48 has no IReadOnlySet) - Add KeyValuePair Deconstruct extension polyfill - Rewrite 8 ArgumentNullException.ThrowIfNull calls inline (PolySharp doesn't polyfill static methods) - Guard CellRef.GetHashCode against null strings (net6 HashCode tolerates null; Microsoft.Bcl.HashCode polyfill does not) - Replace string.StartsWith(char) with the (string, StringComparison) overload - Polyfill Path.GetRelativePath in LambdaFormatTests via Uri.MakeRelativeUri - Update Directory.Build.props to add explicit <Using> items for the net6 implicit-using set (ImplicitUsings is a no-op on net48) Build: 0 errors, 900/900 tests passing. Refs #198
- Flip lambda-boss.dna Pack="true" and add explicit <Reference> entries for each runtime dep (net48 has no deps.json so ExcelDNA's pack step can't auto-enumerate) - Make NativeMethods class + extern methods internal (silences 18 CA1401 warnings now that callers all live in the same assembly) - Delete installer/ entirely: lambda-boss.iss, bundled-runtime/, logo.ico, wizard-*.bmp - Drop installer paths from .gitignore; add release/output/ - Add release/README.txt and release/unblock.cmd as checked-in source files for the zip contents - Add scripts/build-release-bundle.ps1 — stages signed XLL + README + unblock.cmd into LambdaBoss-<version>.zip - Rewrite scripts/publish-release.ps1: drop InnoSetup compile and installer signing steps, drop bundled-runtime preflight, call the new bundle script, attach the zip to the GitHub Release - Update CLAUDE.md: tech stack to net48, polyfill notes, NuGet dependency convention now points at lambda-boss.dna, publishing section reflects zip-only output Packed XLL size: 4.3 MB (64-bit) with all 13 managed deps embedded. Build: 0 errors, 20 warnings (all pre-existing); tests: 900/900 pass. Refs #198
- Bump setup-dotnet to 8.0.x SDK (any modern SDK can build net48; net6 is no longer relevant) - Drop the GitHub Packages authentication step and the `permissions: packages: read` block — Taglo.Excel.Common was the only GH-Packages dependency and is now inlined - Drop the TagloGit feed from addin/nuget.config for the same reason
After inlining Taglo.Excel.Common into lambda-boss.dll, ExcelDNA's auto-registration started scanning Logger, UpdateChecker, and WindowPositioner public static methods as candidate Excel UDFs. Logger and UpdateChecker both expose `Initialize(...)`, which triggered: Registration [Error] Repeated function name: 'Initialize' - previous registration will be overwritten. Also silently registered Logger.Info, Logger.Error, UpdateChecker.ParseVersion and WindowPositioner.CenterOnExcel as Excel functions, which we never wanted. On net6 these methods lived in a separate Taglo.Excel.Common.dll referenced as a dependency (not as an ExternalLibrary), so ExcelDNA didn't scan them. Marking the three helper classes `internal static` keeps the registration scan out — ExcelDNA only picks up public static methods in public classes. NativeMethods is already internal.
CI failed on .NET SDK 8.0.x with: error CS1501: No overload for method 'Contains' takes 2 arguments The `string.Contains(string, StringComparison)` overload is from netstandard 2.1, not net48. Local builds (running .NET SDK 10) accepted it because that SDK's net48 reference assemblies are looser. .NET SDK 8 on CI uses stricter net48 reference assemblies. Switch the two call sites in LambdaPopup.xaml.cs to `IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0`, which is universally available.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implementation of spec 0007 — .NET Framework 4.8 port.
Closes #198.
What's in here
Two commits:
Taglo.Excel.Common, wires up polyfills (PolySharp, Microsoft.Bcl.HashCode, hand-rolledKeyValuePair.Deconstruct), fixes ~15 small net48 BCL gaps. 900/900 unit tests pass.installer/directory entirely, addsrelease/README.txt+release/unblock.cmd+scripts/build-release-bundle.ps1, rewritesscripts/publish-release.ps1to drop InnoSetup steps.Notable findings during execution
gong-wpf-dragdrop 3.2.*andOokii.Dialogs.Wpf 5.0.1already support net48 at the existing version floors. No pinning needed.deps.jsonto read, so it can't auto-enumerate managed dependencies for packing. Each runtime dep needs an explicit<Reference Path="..." Pack="true" />entry inlambda-boss.dna. Captured inCLAUDE.mdas a "when adding NuGet dependencies" convention.Microsoft.Bcl.HashCodeon net48 callsStringComparer.GetHashCode(null)directly and throws, where .NET 6's built-inHashCodetolerates null. Coalesce nullable strings to""in anyGetHashCode()usingStringComparer—CellRef.GetHashCode()needed it, and was the entire cause of 158 test failures on first run before the fix.<ImplicitUsings>enable</ImplicitUsings>is silently a no-op on net48 — added explicit<Using Include="…">items inDirectory.Build.propscovering the .NET 6 implicit-using set so all 69 files using file-scoped namespaces still compile.Release artifact
The packed XLL is
lambda-boss64-packed.xllat 4.3 MB with all 13 managed deps embedded as Win32 resources. Wrapped inLambdaBoss-<version>.zip(~1.2 MB compressed) with README + unblock.cmd.Test plan
dotnet build addin/lambda-boss.slnx -c Release— 0 errors, 20 pre-existing warnings.dotnet test addin/lambda-boss.Tests/lambda-boss.Tests.csproj -c Release— 900/900 pass.dotnet build addin/lambda-boss.AddinTests/lambda-boss.AddinTests.csproj— 0 errors.scripts/build-release-bundle.ps1 -Version <test>— produces a valid zip with the three expected files./Gatherand/Editslash commands. Path:addin/lambda-boss/bin/Release/net48/publish/lambda-boss64-packed.xll.