Skip to content

Commit 630d3db

Browse files
mayukiJoC0de
andauthored
Add option to prefer .NET Standard over .NET Framework as TargetFramework (#641)
* Add option to prefer .NET Standard over .NET Framework as TargetFramework * New NuGet.config has a default preference for .NET Standard over .NET Framework * simplify code + add Tooltip + add Infobox + add unit test --------- Co-authored-by: JoC0de <[email protected]>
1 parent e74a842 commit 630d3db

File tree

5 files changed

+133
-2
lines changed

5 files changed

+133
-2
lines changed

src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs

+60
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,66 @@ public void TryGetBestTargetFrameworkForCurrentSettingsTest(
815815
}
816816
}
817817

818+
[Test]
819+
[TestCase(
820+
"2021.3.16f1",
821+
true,
822+
new[] { "net4.7.2", "netstandard2.0", "unity", "netstandard2.1" },
823+
new[] { "unity", "netstandard2.1", "netstandard2.0", "net4.7.2" })]
824+
[TestCase(
825+
"2021.3.16f1",
826+
false,
827+
new[] { "net4.7.2", "netstandard2.0", "unity", "netstandard2.1" },
828+
new[] { "unity", "net4.7.2", "netstandard2.1", "netstandard2.0" })]
829+
public void TryGetBestTargetFrameworkPreferNetStandardTest(
830+
string unityVersion,
831+
bool preferNetStandard,
832+
string[] availableFrameworks,
833+
string[] expectedBestMatch)
834+
{
835+
var unityVersionType = typeof(UnityVersion);
836+
var currentUnityVersionProperty = unityVersionType.GetProperty(nameof(UnityVersion.Current), BindingFlags.Public | BindingFlags.Static);
837+
Assume.That(currentUnityVersionProperty, Is.Not.Null);
838+
Assume.That(currentUnityVersionProperty.CanRead, Is.True);
839+
Assume.That(currentUnityVersionProperty.CanWrite, Is.True);
840+
841+
var currentBuildTargetApiCompatibilityLevelProperty = typeof(TargetFrameworkResolver).GetProperty(
842+
nameof(TargetFrameworkResolver.CurrentBuildTargetApiCompatibilityLevel),
843+
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
844+
Assume.That(currentBuildTargetApiCompatibilityLevelProperty, Is.Not.Null);
845+
Assume.That(currentBuildTargetApiCompatibilityLevelProperty.CanRead, Is.True);
846+
Assume.That(currentBuildTargetApiCompatibilityLevelProperty.CanWrite, Is.True);
847+
848+
var oldUnityVersion = currentUnityVersionProperty.GetValue(null);
849+
var oldApiCompatibilityLevel = currentBuildTargetApiCompatibilityLevelProperty.GetValue(null);
850+
var oldPreferNetStandardOverNetFramework = ConfigurationManager.PreferNetStandardOverNetFramework;
851+
852+
try
853+
{
854+
currentUnityVersionProperty.SetValue(null, new UnityVersion(unityVersion));
855+
currentBuildTargetApiCompatibilityLevelProperty.SetValue(null, new Lazy<ApiCompatibilityLevel>(() => ApiCompatibilityLevel.NET_4_6));
856+
ConfigurationManager.NugetConfigFile.PreferNetStandardOverNetFramework = preferNetStandard;
857+
858+
var allFrameworks = availableFrameworks.ToList();
859+
var foundBestMatch = new List<string>();
860+
while (allFrameworks.Count > 0)
861+
{
862+
var bestMatch = TargetFrameworkResolver.TryGetBestTargetFrameworkForCurrentSettings(allFrameworks, null);
863+
foundBestMatch.Add(bestMatch);
864+
865+
allFrameworks.RemoveAt(allFrameworks.IndexOf(bestMatch));
866+
}
867+
868+
Assert.That(foundBestMatch, Is.EqualTo(expectedBestMatch));
869+
}
870+
finally
871+
{
872+
currentUnityVersionProperty.SetValue(null, oldUnityVersion);
873+
currentBuildTargetApiCompatibilityLevelProperty.SetValue(null, oldApiCompatibilityLevel);
874+
ConfigurationManager.NugetConfigFile.PreferNetStandardOverNetFramework = oldPreferNetStandardOverNetFramework;
875+
}
876+
}
877+
818878
[Test]
819879
public void TestUpgrading()
820880
{

src/NuGetForUnity/Editor/Configuration/ConfigurationManager.cs

+5
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ public static NugetConfigFile NugetConfigFile
8686
/// </summary>
8787
internal static bool IsVerboseLoggingEnabled => nugetConfigFile?.Verbose ?? false;
8888

89+
/// <summary>
90+
/// Gets the value indicating whether .NET Standard is preferred over .NET Framework as the TargetFramework.
91+
/// </summary>
92+
internal static bool PreferNetStandardOverNetFramework => nugetConfigFile?.PreferNetStandardOverNetFramework ?? false;
93+
8994
/// <summary>
9095
/// Gets the <see cref="INugetPackageSource" /> to use.
9196
/// </summary>

src/NuGetForUnity/Editor/Configuration/NugetConfigFile.cs

+20
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public class NugetConfigFile
5252

5353
private const string PackagesConfigDirectoryPathConfigKey = "PackagesConfigDirectoryPath";
5454

55+
private const string PreferNetStandardOverNetFrameworkConfigKey = "PreferNetStandardOverNetFramework";
56+
5557
private const string ProtocolVersionAttributeName = "protocolVersion";
5658

5759
private const string PasswordAttributeName = "password";
@@ -186,6 +188,11 @@ public string RelativePackagesConfigDirectoryPath
186188
/// </summary>
187189
public int RequestTimeoutSeconds { get; set; } = DefaultRequestTimeout;
188190

191+
/// <summary>
192+
/// Gets or sets the value indicating whether .NET Standard is preferred over .NET Framework as the TargetFramework.
193+
/// </summary>
194+
public bool PreferNetStandardOverNetFramework { get; set; }
195+
189196
/// <summary>
190197
/// Gets the value that tells the system how to determine where the packages are to be installed and configurations are to be stored.
191198
/// </summary>
@@ -380,6 +387,10 @@ public static NugetConfigFile Load([NotNull] string filePath)
380387
{
381388
configFile.RelativePackagesConfigDirectoryPath = value;
382389
}
390+
else if (string.Equals(key, PreferNetStandardOverNetFrameworkConfigKey, StringComparison.OrdinalIgnoreCase))
391+
{
392+
configFile.PreferNetStandardOverNetFramework = bool.Parse(value);
393+
}
383394
}
384395

385396
return configFile;
@@ -408,6 +419,7 @@ public static NugetConfigFile CreateDefaultFile([NotNull] string filePath)
408419
<add key=""repositoryPath"" value=""./Packages"" />
409420
<add key=""PackagesConfigDirectoryPath"" value=""."" />
410421
<add key=""slimRestore"" value=""true"" />
422+
<add key=""PreferNetStandardOverNetFramework"" value=""true"" />
411423
</config>
412424
</configuration>";
413425

@@ -562,6 +574,14 @@ public void Save([NotNull] string filePath)
562574
config.Add(addElement);
563575
}
564576

577+
if (PreferNetStandardOverNetFramework)
578+
{
579+
addElement = new XElement("add");
580+
addElement.Add(new XAttribute("key", PreferNetStandardOverNetFrameworkConfigKey));
581+
addElement.Add(new XAttribute("value", PreferNetStandardOverNetFramework.ToString().ToLowerInvariant()));
582+
config.Add(addElement);
583+
}
584+
565585
var configuration = new XElement("configuration");
566586
configuration.Add(packageSources);
567587
configuration.Add(disabledPackageSources);

src/NuGetForUnity/Editor/TargetFrameworkResolver.cs

+29-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Collections.Generic;
99
using System.Linq;
1010
using JetBrains.Annotations;
11+
using NugetForUnity.Configuration;
1112
using NugetForUnity.Models;
1213
using UnityEditor;
1314

@@ -106,6 +107,30 @@ internal static class TargetFrameworkResolver
106107
new TargetFrameworkSupport(string.Empty),
107108
};
108109

110+
// Almost same as PrioritizedTargetFrameworks, but it prefers .NET Standard 2.x over .NET Framework.
111+
[NotNull]
112+
private static readonly TargetFrameworkSupport[] PrioritizedTargetFrameworksPreferNetStandard20Or21;
113+
114+
static TargetFrameworkResolver()
115+
{
116+
PrioritizedTargetFrameworksPreferNetStandard20Or21 = PrioritizedTargetFrameworks.OrderBy(
117+
framework =>
118+
{
119+
switch (framework.Name)
120+
{
121+
case "unity":
122+
return 1; // keep it first
123+
case "netstandard21":
124+
return 2; // Prefer .NET Standard 2.x over .NET Framework
125+
case "netstandard20":
126+
return 3; // Prefer .NET Standard 2.x over .NET Framework
127+
default:
128+
return 4; // keep the rest in the same order as before
129+
}
130+
})
131+
.ToArray();
132+
}
133+
109134
/// <summary>
110135
/// Gets the <see cref="ApiCompatibilityLevel" /> of the current selected build target.
111136
/// </summary>
@@ -191,7 +216,10 @@ public static T TryGetBestTargetFramework<T>(
191216

192217
var currentDotnetVersion = CurrentBuildTargetDotnetVersionCompatibilityLevel;
193218
var currentUnityVersion = UnityVersion.Current;
194-
foreach (var targetFrameworkSupport in PrioritizedTargetFrameworks)
219+
var prioritizedTargetFrameworks = ConfigurationManager.PreferNetStandardOverNetFramework ?
220+
PrioritizedTargetFrameworksPreferNetStandard20Or21 :
221+
PrioritizedTargetFrameworks;
222+
foreach (var targetFrameworkSupport in prioritizedTargetFrameworks)
195223
{
196224
if (targetFrameworkSupport.SupportedDotnetVersions.Length != 0 &&
197225
!targetFrameworkSupport.SupportedDotnetVersions.Contains(currentDotnetVersion))

src/NuGetForUnity/Editor/Ui/NugetPreferences.cs

+19-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public override void OnGUI([CanBeNull] string searchContext)
112112
var sourcePathChangedThisFrame = false;
113113
var needsAssetRefresh = false;
114114

115-
var biggestLabelSize = EditorStyles.label.CalcSize(new GUIContent("Request Timeout in seconds")).x;
115+
var biggestLabelSize = EditorStyles.label.CalcSize(new GUIContent("Prefer .NET Standard dependencies over .NET Framework")).x;
116116
EditorGUIUtility.labelWidth = biggestLabelSize;
117117
EditorGUILayout.LabelField($"Version: {NuGetForUnityVersion}");
118118

@@ -244,6 +244,24 @@ public override void OnGUI([CanBeNull] string searchContext)
244244
}
245245
}
246246

247+
var preferNetStandardOverNetFramework = EditorGUILayout.Toggle(
248+
new GUIContent(
249+
"Prefer .NET Standard dependencies over .NET Framework",
250+
"If a nuget package contains DLL's for .NET Framework an .NET Standard the .NET Standard DLL's are preferred."),
251+
ConfigurationManager.NugetConfigFile.PreferNetStandardOverNetFramework);
252+
if (preferNetStandardOverNetFramework != ConfigurationManager.NugetConfigFile.PreferNetStandardOverNetFramework)
253+
{
254+
preferencesChangedThisFrame = true;
255+
ConfigurationManager.NugetConfigFile.PreferNetStandardOverNetFramework = preferNetStandardOverNetFramework;
256+
}
257+
258+
if (TargetFrameworkResolver.CurrentBuildTargetApiCompatibilityLevel.Value == ApiCompatibilityLevel.NET_Standard_2_0)
259+
{
260+
EditorGUILayout.HelpBox(
261+
"The prefer .NET Standard setting has no effect as you have set the API compatibility level to .NET Standard so .NET Standard will always be preferred, as it is the only supported.",
262+
MessageType.Info);
263+
}
264+
247265
var requestTimeout = EditorGUILayout.IntField(
248266
new GUIContent(
249267
"Request Timeout in seconds",

0 commit comments

Comments
 (0)