From ca41201b95f7445414f5b059e02d1361f3a710a8 Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:17:59 -0500 Subject: [PATCH 1/3] Adjust emited project structure when selected target framework is .NET Framework by omitting ImplicitUsings.cs and omitting nullable setting in .csproj file. --- .../Wizards/VsReqnrollProjectWizard.cs | 27 +++++++++++++++++++ .../ProjectTemplate.csproj | 4 +-- .../CalculatorStepDefinitions.cs | 2 ++ .../AddNewReqnrollProjectViewModel.cs | 2 ++ .../Infrastructure/WizardRunParameters.cs | 1 + .../Wizards/ReqnrollProjectWizard.cs | 1 + 6 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Reqnroll.VisualStudio.Package/Wizards/VsReqnrollProjectWizard.cs b/Reqnroll.VisualStudio.Package/Wizards/VsReqnrollProjectWizard.cs index 03e2b43a..c38def68 100644 --- a/Reqnroll.VisualStudio.Package/Wizards/VsReqnrollProjectWizard.cs +++ b/Reqnroll.VisualStudio.Package/Wizards/VsReqnrollProjectWizard.cs @@ -6,4 +6,31 @@ namespace Reqnroll.VisualStudio.Wizards; public class VsReqnrollProjectWizard : VsProjectScopeWizard { + + public override bool ShouldAddProjectItem(string filePath) + { + if (!base.ShouldAddProjectItem(filePath)) + return false; + + // Exclude ImplicitUsings.cs for .NET Framework projects + if (filePath.EndsWith("ImplicitUsings.cs", StringComparison.OrdinalIgnoreCase) && ShouldExcludeImplicitUsings()) + { + return false; + } + + return true; + } + + private bool ShouldExcludeImplicitUsings() + { + if (_wizardRunParameters?.ReplacementsDictionary == null) + return false; + + var isNetFramework = _wizardRunParameters.ReplacementsDictionary.TryGetValue(WizardRunParameters.IsNetFrameworkKey, out var isNetFx) + && bool.Parse(isNetFx); + + // ImplicitUsings only makes sense for C# 10+ (.NET 6+) + // For .NET Framework or older SDKs, remove it + return isNetFramework; + } } diff --git a/Reqnroll.VisualStudio.ProjectTemplate/ProjectTemplate.csproj b/Reqnroll.VisualStudio.ProjectTemplate/ProjectTemplate.csproj index e83aa004..e415e4ed 100644 --- a/Reqnroll.VisualStudio.ProjectTemplate/ProjectTemplate.csproj +++ b/Reqnroll.VisualStudio.ProjectTemplate/ProjectTemplate.csproj @@ -1,9 +1,9 @@ - $dotnetframework$ + $dotnetframework$$if$ ('$isnetframework$' == 'False') enable - enable$if$ ('$rootnamespace$' != '') + enable$endif$$if$ ('$rootnamespace$' != '') $rootnamespace$$endif$ diff --git a/Reqnroll.VisualStudio.ProjectTemplate/StepDefinitions/CalculatorStepDefinitions.cs b/Reqnroll.VisualStudio.ProjectTemplate/StepDefinitions/CalculatorStepDefinitions.cs index 9f605381..f9e534df 100644 --- a/Reqnroll.VisualStudio.ProjectTemplate/StepDefinitions/CalculatorStepDefinitions.cs +++ b/Reqnroll.VisualStudio.ProjectTemplate/StepDefinitions/CalculatorStepDefinitions.cs @@ -1,3 +1,5 @@ +$if$ ('$isnetframework$' == 'True') +using Reqnroll;$endif$ namespace $safeprojectname$.StepDefinitions; [Binding] diff --git a/Reqnroll.VisualStudio/UI/ViewModels/AddNewReqnrollProjectViewModel.cs b/Reqnroll.VisualStudio/UI/ViewModels/AddNewReqnrollProjectViewModel.cs index 00082852..b26ea897 100644 --- a/Reqnroll.VisualStudio/UI/ViewModels/AddNewReqnrollProjectViewModel.cs +++ b/Reqnroll.VisualStudio/UI/ViewModels/AddNewReqnrollProjectViewModel.cs @@ -28,6 +28,8 @@ public string DotNetFramework } } + public bool IsNetFramework => DotNetFramework.StartsWith("net4", StringComparison.InvariantCultureIgnoreCase); + public string UnitTestFramework { get; set; } = MsTest; // FluentAssertions suggestion is temporarily hidden from the UI as it is not free for commercial use anymore. // See https://xceed.com/fluent-assertions-faq/ diff --git a/Reqnroll.VisualStudio/Wizards/Infrastructure/WizardRunParameters.cs b/Reqnroll.VisualStudio/Wizards/Infrastructure/WizardRunParameters.cs index a418715a..52a921af 100644 --- a/Reqnroll.VisualStudio/Wizards/Infrastructure/WizardRunParameters.cs +++ b/Reqnroll.VisualStudio/Wizards/Infrastructure/WizardRunParameters.cs @@ -5,6 +5,7 @@ public class WizardRunParameters public const string CustomToolSettingKey = "$customtool$"; public const string BuildActionKey = "$buildaction$"; public const string CopyToOutputDirectoryKey = "$copytooutputdir$"; + public const string IsNetFrameworkKey = "$isnetframework$"; public WizardRunParameters(bool isAddNewItem, IProjectScope projectScope, IIdeScope ideScope, string templateFolder, string targetFolder, string targetFileName, Dictionary replacementsDictionary) diff --git a/Reqnroll.VisualStudio/Wizards/ReqnrollProjectWizard.cs b/Reqnroll.VisualStudio/Wizards/ReqnrollProjectWizard.cs index 2a3bf03c..ed1295d9 100644 --- a/Reqnroll.VisualStudio/Wizards/ReqnrollProjectWizard.cs +++ b/Reqnroll.VisualStudio/Wizards/ReqnrollProjectWizard.cs @@ -44,6 +44,7 @@ public bool RunStarted(WizardRunParameters wizardRunParameters) // Add custom parameters. wizardRunParameters.ReplacementsDictionary.Add("$dotnetframework$", viewModel.DotNetFramework); + wizardRunParameters.ReplacementsDictionary.Add(WizardRunParameters.IsNetFrameworkKey, viewModel.IsNetFramework.ToString(CultureInfo.InvariantCulture)); wizardRunParameters.ReplacementsDictionary.Add("$unittestframework$", viewModel.UnitTestFramework); wizardRunParameters.ReplacementsDictionary.Add("$fluentassertionsincluded$", viewModel.FluentAssertionsIncluded.ToString(CultureInfo.InvariantCulture)); From 93550781db7f088357792052373a27318c316689 Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:24:46 -0500 Subject: [PATCH 2/3] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8e8c73c..4729cb92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,9 @@ ## Improvements: ## Bug fixes: +* Fix #133 - Project Templates are broken for .NET Framework -*Contributors of this release (in alphabetical order):* +*Contributors of this release (in alphabetical order):* @clrudolphi # v2026.1.477 - 2026-01-28 From 81c3a5cfad21c506cf96c4d737a29ccbf50f1c8f Mon Sep 17 00:00:00 2001 From: Chris Rudolphi <1702962+clrudolphi@users.noreply.github.com> Date: Fri, 20 Mar 2026 18:01:29 -0500 Subject: [PATCH 3/3] Moved global usings to the csproj file. --- .../Wizards/VsReqnrollProjectWizard.cs | 27 ------------------- .../ImplicitUsings.cs | 5 ---- .../ProjectTemplate.csproj | 6 +++-- ...qnroll.VisualStudio.ProjectTemplate.csproj | 2 -- ...ll.VisualStudio.ProjectTemplate.vstemplate | 1 - .../Wizards/ReqnrollProjectWizard.cs | 27 +++++++++++++++++++ 6 files changed, 31 insertions(+), 37 deletions(-) delete mode 100644 Reqnroll.VisualStudio.ProjectTemplate/ImplicitUsings.cs diff --git a/Reqnroll.VisualStudio.Package/Wizards/VsReqnrollProjectWizard.cs b/Reqnroll.VisualStudio.Package/Wizards/VsReqnrollProjectWizard.cs index c38def68..03e2b43a 100644 --- a/Reqnroll.VisualStudio.Package/Wizards/VsReqnrollProjectWizard.cs +++ b/Reqnroll.VisualStudio.Package/Wizards/VsReqnrollProjectWizard.cs @@ -6,31 +6,4 @@ namespace Reqnroll.VisualStudio.Wizards; public class VsReqnrollProjectWizard : VsProjectScopeWizard { - - public override bool ShouldAddProjectItem(string filePath) - { - if (!base.ShouldAddProjectItem(filePath)) - return false; - - // Exclude ImplicitUsings.cs for .NET Framework projects - if (filePath.EndsWith("ImplicitUsings.cs", StringComparison.OrdinalIgnoreCase) && ShouldExcludeImplicitUsings()) - { - return false; - } - - return true; - } - - private bool ShouldExcludeImplicitUsings() - { - if (_wizardRunParameters?.ReplacementsDictionary == null) - return false; - - var isNetFramework = _wizardRunParameters.ReplacementsDictionary.TryGetValue(WizardRunParameters.IsNetFrameworkKey, out var isNetFx) - && bool.Parse(isNetFx); - - // ImplicitUsings only makes sense for C# 10+ (.NET 6+) - // For .NET Framework or older SDKs, remove it - return isNetFramework; - } } diff --git a/Reqnroll.VisualStudio.ProjectTemplate/ImplicitUsings.cs b/Reqnroll.VisualStudio.ProjectTemplate/ImplicitUsings.cs deleted file mode 100644 index ed4cec87..00000000 --- a/Reqnroll.VisualStudio.ProjectTemplate/ImplicitUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -global using Reqnroll;$if$ ('$unittestframework$' == 'NUnit') -global using NUnit;$endif$$if$ ('$unittestframework$' == 'MSTest') -global using Microsoft.VisualStudio.TestTools.UnitTesting;$endif$$if$ ('$unittestframework$' == 'xUnit') -global using Xunit;$endif$$if$ ('$fluentassertionsincluded$' == 'True') -global using FluentAssertions;$endif$ diff --git a/Reqnroll.VisualStudio.ProjectTemplate/ProjectTemplate.csproj b/Reqnroll.VisualStudio.ProjectTemplate/ProjectTemplate.csproj index 1c415e1f..054b24a5 100644 --- a/Reqnroll.VisualStudio.ProjectTemplate/ProjectTemplate.csproj +++ b/Reqnroll.VisualStudio.ProjectTemplate/ProjectTemplate.csproj @@ -30,6 +30,8 @@ - - + $if$ ('$isnetframework$' == 'False') + + +$globalUsings$ $endif$ diff --git a/Reqnroll.VisualStudio.ProjectTemplate/Reqnroll.VisualStudio.ProjectTemplate.csproj b/Reqnroll.VisualStudio.ProjectTemplate/Reqnroll.VisualStudio.ProjectTemplate.csproj index 84e7a371..15826dd0 100644 --- a/Reqnroll.VisualStudio.ProjectTemplate/Reqnroll.VisualStudio.ProjectTemplate.csproj +++ b/Reqnroll.VisualStudio.ProjectTemplate/Reqnroll.VisualStudio.ProjectTemplate.csproj @@ -17,12 +17,10 @@ - - diff --git a/Reqnroll.VisualStudio.ProjectTemplate/Reqnroll.VisualStudio.ProjectTemplate.vstemplate b/Reqnroll.VisualStudio.ProjectTemplate/Reqnroll.VisualStudio.ProjectTemplate.vstemplate index e21b55e4..f2e89b95 100644 --- a/Reqnroll.VisualStudio.ProjectTemplate/Reqnroll.VisualStudio.ProjectTemplate.vstemplate +++ b/Reqnroll.VisualStudio.ProjectTemplate/Reqnroll.VisualStudio.ProjectTemplate.vstemplate @@ -22,7 +22,6 @@ Features\Calculator.feature StepDefinitions\CalculatorStepDefinitions.cs - ImplicitUsings.cs diff --git a/Reqnroll.VisualStudio/Wizards/ReqnrollProjectWizard.cs b/Reqnroll.VisualStudio/Wizards/ReqnrollProjectWizard.cs index ed1295d9..4dd6d5af 100644 --- a/Reqnroll.VisualStudio/Wizards/ReqnrollProjectWizard.cs +++ b/Reqnroll.VisualStudio/Wizards/ReqnrollProjectWizard.cs @@ -50,6 +50,33 @@ public bool RunStarted(WizardRunParameters wizardRunParameters) viewModel.FluentAssertionsIncluded.ToString(CultureInfo.InvariantCulture)); wizardRunParameters.ReplacementsDictionary.Add("$rootnamespace$", rootNamespace); + if (!viewModel.IsNetFramework) + { + // For .NET 8+ projects, we will create a set of global usings to be inserted in to the project file. This is in leiu of adding a `GlobalUsings.cs` file. + var globalUsings = new StringBuilder(); + switch (viewModel.UnitTestFramework) + { + case "MSTest": + globalUsings.AppendLine(" "); + break; + case "NUnit": + globalUsings.AppendLine(" "); + break; + case "xUnit": + case "XUnit.v3": + globalUsings.AppendLine(" "); + break; + // For TUnit, no global using is required. + default: + break; + } + if (viewModel.FluentAssertionsIncluded) + { + globalUsings.AppendLine(" "); + } + wizardRunParameters.ReplacementsDictionary.Add("$globalUsings$", globalUsings.ToString()); + } + return true; } }