Skip to content

Commit

Permalink
Add option to prefer .NET Standard over .NET Framework as TargetFrame…
Browse files Browse the repository at this point in the history
…work (#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]>
  • Loading branch information
mayuki and JoC0de authored Jun 1, 2024
1 parent e74a842 commit 630d3db
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 2 deletions.
60 changes: 60 additions & 0 deletions src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,66 @@ public void TryGetBestTargetFrameworkForCurrentSettingsTest(
}
}

[Test]
[TestCase(
"2021.3.16f1",
true,
new[] { "net4.7.2", "netstandard2.0", "unity", "netstandard2.1" },
new[] { "unity", "netstandard2.1", "netstandard2.0", "net4.7.2" })]
[TestCase(
"2021.3.16f1",
false,
new[] { "net4.7.2", "netstandard2.0", "unity", "netstandard2.1" },
new[] { "unity", "net4.7.2", "netstandard2.1", "netstandard2.0" })]
public void TryGetBestTargetFrameworkPreferNetStandardTest(
string unityVersion,
bool preferNetStandard,
string[] availableFrameworks,
string[] expectedBestMatch)
{
var unityVersionType = typeof(UnityVersion);
var currentUnityVersionProperty = unityVersionType.GetProperty(nameof(UnityVersion.Current), BindingFlags.Public | BindingFlags.Static);
Assume.That(currentUnityVersionProperty, Is.Not.Null);
Assume.That(currentUnityVersionProperty.CanRead, Is.True);
Assume.That(currentUnityVersionProperty.CanWrite, Is.True);

var currentBuildTargetApiCompatibilityLevelProperty = typeof(TargetFrameworkResolver).GetProperty(
nameof(TargetFrameworkResolver.CurrentBuildTargetApiCompatibilityLevel),
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
Assume.That(currentBuildTargetApiCompatibilityLevelProperty, Is.Not.Null);
Assume.That(currentBuildTargetApiCompatibilityLevelProperty.CanRead, Is.True);
Assume.That(currentBuildTargetApiCompatibilityLevelProperty.CanWrite, Is.True);

var oldUnityVersion = currentUnityVersionProperty.GetValue(null);
var oldApiCompatibilityLevel = currentBuildTargetApiCompatibilityLevelProperty.GetValue(null);
var oldPreferNetStandardOverNetFramework = ConfigurationManager.PreferNetStandardOverNetFramework;

try
{
currentUnityVersionProperty.SetValue(null, new UnityVersion(unityVersion));
currentBuildTargetApiCompatibilityLevelProperty.SetValue(null, new Lazy<ApiCompatibilityLevel>(() => ApiCompatibilityLevel.NET_4_6));
ConfigurationManager.NugetConfigFile.PreferNetStandardOverNetFramework = preferNetStandard;

var allFrameworks = availableFrameworks.ToList();
var foundBestMatch = new List<string>();
while (allFrameworks.Count > 0)
{
var bestMatch = TargetFrameworkResolver.TryGetBestTargetFrameworkForCurrentSettings(allFrameworks, null);
foundBestMatch.Add(bestMatch);

allFrameworks.RemoveAt(allFrameworks.IndexOf(bestMatch));
}

Assert.That(foundBestMatch, Is.EqualTo(expectedBestMatch));
}
finally
{
currentUnityVersionProperty.SetValue(null, oldUnityVersion);
currentBuildTargetApiCompatibilityLevelProperty.SetValue(null, oldApiCompatibilityLevel);
ConfigurationManager.NugetConfigFile.PreferNetStandardOverNetFramework = oldPreferNetStandardOverNetFramework;
}
}

[Test]
public void TestUpgrading()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ public static NugetConfigFile NugetConfigFile
/// </summary>
internal static bool IsVerboseLoggingEnabled => nugetConfigFile?.Verbose ?? false;

/// <summary>
/// Gets the value indicating whether .NET Standard is preferred over .NET Framework as the TargetFramework.
/// </summary>
internal static bool PreferNetStandardOverNetFramework => nugetConfigFile?.PreferNetStandardOverNetFramework ?? false;

/// <summary>
/// Gets the <see cref="INugetPackageSource" /> to use.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions src/NuGetForUnity/Editor/Configuration/NugetConfigFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public class NugetConfigFile

private const string PackagesConfigDirectoryPathConfigKey = "PackagesConfigDirectoryPath";

private const string PreferNetStandardOverNetFrameworkConfigKey = "PreferNetStandardOverNetFramework";

private const string ProtocolVersionAttributeName = "protocolVersion";

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

/// <summary>
/// Gets or sets the value indicating whether .NET Standard is preferred over .NET Framework as the TargetFramework.
/// </summary>
public bool PreferNetStandardOverNetFramework { get; set; }

/// <summary>
/// Gets the value that tells the system how to determine where the packages are to be installed and configurations are to be stored.
/// </summary>
Expand Down Expand Up @@ -380,6 +387,10 @@ public static NugetConfigFile Load([NotNull] string filePath)
{
configFile.RelativePackagesConfigDirectoryPath = value;
}
else if (string.Equals(key, PreferNetStandardOverNetFrameworkConfigKey, StringComparison.OrdinalIgnoreCase))
{
configFile.PreferNetStandardOverNetFramework = bool.Parse(value);
}
}

return configFile;
Expand Down Expand Up @@ -408,6 +419,7 @@ public static NugetConfigFile CreateDefaultFile([NotNull] string filePath)
<add key=""repositoryPath"" value=""./Packages"" />
<add key=""PackagesConfigDirectoryPath"" value=""."" />
<add key=""slimRestore"" value=""true"" />
<add key=""PreferNetStandardOverNetFramework"" value=""true"" />
</config>
</configuration>";

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

if (PreferNetStandardOverNetFramework)
{
addElement = new XElement("add");
addElement.Add(new XAttribute("key", PreferNetStandardOverNetFrameworkConfigKey));
addElement.Add(new XAttribute("value", PreferNetStandardOverNetFramework.ToString().ToLowerInvariant()));
config.Add(addElement);
}

var configuration = new XElement("configuration");
configuration.Add(packageSources);
configuration.Add(disabledPackageSources);
Expand Down
30 changes: 29 additions & 1 deletion src/NuGetForUnity/Editor/TargetFrameworkResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using NugetForUnity.Configuration;
using NugetForUnity.Models;
using UnityEditor;

Expand Down Expand Up @@ -106,6 +107,30 @@ internal static class TargetFrameworkResolver
new TargetFrameworkSupport(string.Empty),
};

// Almost same as PrioritizedTargetFrameworks, but it prefers .NET Standard 2.x over .NET Framework.
[NotNull]
private static readonly TargetFrameworkSupport[] PrioritizedTargetFrameworksPreferNetStandard20Or21;

static TargetFrameworkResolver()
{
PrioritizedTargetFrameworksPreferNetStandard20Or21 = PrioritizedTargetFrameworks.OrderBy(
framework =>
{
switch (framework.Name)
{
case "unity":
return 1; // keep it first
case "netstandard21":
return 2; // Prefer .NET Standard 2.x over .NET Framework
case "netstandard20":
return 3; // Prefer .NET Standard 2.x over .NET Framework
default:
return 4; // keep the rest in the same order as before
}
})
.ToArray();
}

/// <summary>
/// Gets the <see cref="ApiCompatibilityLevel" /> of the current selected build target.
/// </summary>
Expand Down Expand Up @@ -191,7 +216,10 @@ public static T TryGetBestTargetFramework<T>(

var currentDotnetVersion = CurrentBuildTargetDotnetVersionCompatibilityLevel;
var currentUnityVersion = UnityVersion.Current;
foreach (var targetFrameworkSupport in PrioritizedTargetFrameworks)
var prioritizedTargetFrameworks = ConfigurationManager.PreferNetStandardOverNetFramework ?
PrioritizedTargetFrameworksPreferNetStandard20Or21 :
PrioritizedTargetFrameworks;
foreach (var targetFrameworkSupport in prioritizedTargetFrameworks)
{
if (targetFrameworkSupport.SupportedDotnetVersions.Length != 0 &&
!targetFrameworkSupport.SupportedDotnetVersions.Contains(currentDotnetVersion))
Expand Down
20 changes: 19 additions & 1 deletion src/NuGetForUnity/Editor/Ui/NugetPreferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public override void OnGUI([CanBeNull] string searchContext)
var sourcePathChangedThisFrame = false;
var needsAssetRefresh = false;

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

Expand Down Expand Up @@ -244,6 +244,24 @@ public override void OnGUI([CanBeNull] string searchContext)
}
}

var preferNetStandardOverNetFramework = EditorGUILayout.Toggle(
new GUIContent(
"Prefer .NET Standard dependencies over .NET Framework",
"If a nuget package contains DLL's for .NET Framework an .NET Standard the .NET Standard DLL's are preferred."),
ConfigurationManager.NugetConfigFile.PreferNetStandardOverNetFramework);
if (preferNetStandardOverNetFramework != ConfigurationManager.NugetConfigFile.PreferNetStandardOverNetFramework)
{
preferencesChangedThisFrame = true;
ConfigurationManager.NugetConfigFile.PreferNetStandardOverNetFramework = preferNetStandardOverNetFramework;
}

if (TargetFrameworkResolver.CurrentBuildTargetApiCompatibilityLevel.Value == ApiCompatibilityLevel.NET_Standard_2_0)
{
EditorGUILayout.HelpBox(
"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.",
MessageType.Info);
}

var requestTimeout = EditorGUILayout.IntField(
new GUIContent(
"Request Timeout in seconds",
Expand Down

0 comments on commit 630d3db

Please sign in to comment.