diff --git a/eng/Packages.props b/eng/Packages.props
index b8ebc96c259..1a98130d455 100644
--- a/eng/Packages.props
+++ b/eng/Packages.props
@@ -18,6 +18,7 @@
+
diff --git a/src/Build.UnitTests/Evaluation/Expander_Tests.cs b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
index bd80b78d7d3..01e62af024a 100644
--- a/src/Build.UnitTests/Evaluation/Expander_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
@@ -2800,34 +2800,23 @@ public void PropertyFunctionVersionComparisonsFailsWithInvalidArguments(string b
var expander = new Expander(pg, FileSystems.Default);
string expectedMessage = ResourceUtilities.GetResourceString("InvalidVersionFormat");
- AssertThrows($"$([MSBuild]::VersionGreaterThan('{badVersion}', '1.0.0'))");
- AssertThrows($"$([MSBuild]::VersionGreaterThan('1.0.0', '{badVersion}'))");
+ AssertThrows(expander, $"$([MSBuild]::VersionGreaterThan('{badVersion}', '1.0.0'))", expectedMessage);
+ AssertThrows(expander, $"$([MSBuild]::VersionGreaterThan('1.0.0', '{badVersion}'))", expectedMessage);
- AssertThrows($"$([MSBuild]::VersionGreaterThanOrEquals('{badVersion}', '1.0.0'))");
- AssertThrows($"$([MSBuild]::VersionGreaterThanOrEquals('1.0.0', '{badVersion}'))");
+ AssertThrows(expander, $"$([MSBuild]::VersionGreaterThanOrEquals('{badVersion}', '1.0.0'))", expectedMessage);
+ AssertThrows(expander, $"$([MSBuild]::VersionGreaterThanOrEquals('1.0.0', '{badVersion}'))", expectedMessage);
- AssertThrows($"$([MSBuild]::VersionLessThan('{badVersion}', '1.0.0'))");
- AssertThrows($"$([MSBuild]::VersionLessThan('1.0.0', '{badVersion}'))");
+ AssertThrows(expander, $"$([MSBuild]::VersionLessThan('{badVersion}', '1.0.0'))", expectedMessage);
+ AssertThrows(expander, $"$([MSBuild]::VersionLessThan('1.0.0', '{badVersion}'))", expectedMessage);
- AssertThrows($"$([MSBuild]::VersionLessThanOrEquals('{badVersion}', '1.0.0'))");
- AssertThrows($"$([MSBuild]::VersionLessThanOrEquals('1.0.0', '{badVersion}'))");
+ AssertThrows(expander, $"$([MSBuild]::VersionLessThanOrEquals('{badVersion}', '1.0.0'))", expectedMessage);
+ AssertThrows(expander, $"$([MSBuild]::VersionLessThanOrEquals('1.0.0', '{badVersion}'))", expectedMessage);
- AssertThrows($"$([MSBuild]::VersionEquals('{badVersion}', '1.0.0'))");
- AssertThrows($"$([MSBuild]::VersionEquals('1.0.0', '{badVersion}'))");
+ AssertThrows(expander, $"$([MSBuild]::VersionEquals('{badVersion}', '1.0.0'))", expectedMessage);
+ AssertThrows(expander, $"$([MSBuild]::VersionEquals('1.0.0', '{badVersion}'))", expectedMessage);
- AssertThrows($"$([MSBuild]::VersionNotEquals('{badVersion}', '1.0.0'))");
- AssertThrows($"$([MSBuild]::VersionNotEquals('1.0.0', '{badVersion}'))");
-
- void AssertThrows(string expression)
- {
- var ex = Assert.Throws(
- () => expander.ExpandPropertiesLeaveTypedAndEscaped(
- expression,
- ExpanderOptions.ExpandProperties,
- MockElementLocation.Instance));
-
- Assert.Contains(expectedMessage, ex.Message);
- }
+ AssertThrows(expander, $"$([MSBuild]::VersionNotEquals('{badVersion}', '1.0.0'))", expectedMessage);
+ AssertThrows(expander, $"$([MSBuild]::VersionNotEquals('1.0.0', '{badVersion}'))", expectedMessage);
}
[Theory]
@@ -2843,22 +2832,64 @@ public void PropertyFunctionVersionComparisons(string a, string b, int expectedS
var pg = new PropertyDictionary();
var expander = new Expander(pg, FileSystems.Default);
- AssertSuccess(expectedSign > 0, $"$([MSBuild]::VersionGreaterThan('{a}', '{b}'))");
- AssertSuccess(expectedSign >= 0, $"$([MSBuild]::VersionGreaterThanOrEquals('{a}', '{b}'))");
- AssertSuccess(expectedSign < 0, $"$([MSBuild]::VersionLessThan('{a}', '{b}'))");
- AssertSuccess(expectedSign <= 0, $"$([MSBuild]::VersionLessThanOrEquals('{a}', '{b}'))");
- AssertSuccess(expectedSign == 0, $"$([MSBuild]::VersionEquals('{a}', '{b}'))");
- AssertSuccess(expectedSign != 0, $"$([MSBuild]::VersionNotEquals('{a}', '{b}'))");
+ AssertSuccess(expander, expectedSign > 0, $"$([MSBuild]::VersionGreaterThan('{a}', '{b}'))");
+ AssertSuccess(expander, expectedSign >= 0, $"$([MSBuild]::VersionGreaterThanOrEquals('{a}', '{b}'))");
+ AssertSuccess(expander, expectedSign < 0, $"$([MSBuild]::VersionLessThan('{a}', '{b}'))");
+ AssertSuccess(expander, expectedSign <= 0, $"$([MSBuild]::VersionLessThanOrEquals('{a}', '{b}'))");
+ AssertSuccess(expander, expectedSign == 0, $"$([MSBuild]::VersionEquals('{a}', '{b}'))");
+ AssertSuccess(expander, expectedSign != 0, $"$([MSBuild]::VersionNotEquals('{a}', '{b}'))");
+ }
- void AssertSuccess(bool expected, string expression)
- {
- bool actual = (bool)expander.ExpandPropertiesLeaveTypedAndEscaped(
+ [Theory]
+ [InlineData("net45", ".NETFramework", "4.5")]
+ [InlineData("netcoreapp3.1", ".NETCoreApp", "3.1")]
+ [InlineData("netstandard2.1", ".NETStandard", "2.1")]
+ [InlineData("foo", "Unsupported", "0.0")]
+ public void PropertyFunctionTargetFrameworkParsing(string tfm, string expectedIdentifier, string expectedVersion)
+ {
+ var pg = new PropertyDictionary();
+ var expander = new Expander(pg, FileSystems.Default);
+
+ AssertSuccess(expander, expectedIdentifier, $"$([MSBuild]::GetTargetFrameworkIdentifier('{tfm}'))");
+ AssertSuccess(expander, expectedVersion, $"$([MSBuild]::GetTargetFrameworkVersion('{tfm}'))");
+ }
+
+ [Theory]
+ [InlineData("net5.0", "net5.0", true)]
+ [InlineData("net45", "net46", false)]
+ [InlineData("net46", "net45", true)]
+ [InlineData("netcoreapp3.1", "netcoreapp1.0", true)]
+ [InlineData("netstandard1.6", "netstandard2.1", false)]
+ [InlineData("netcoreapp3.0", "netstandard2.1", true)]
+ [InlineData("net461", "netstandard1.0", true)]
+ [InlineData("foo", "netstandard1.0", false)]
+ public void PropertyFunctionTargetFrameworkComparisons(string tfm1, string tfm2, bool expectedFrameworkCompatible)
+ {
+ var pg = new PropertyDictionary();
+ var expander = new Expander(pg, FileSystems.Default);
+
+ AssertSuccess(expander, expectedFrameworkCompatible, $"$([MSBuild]::IsTargetFrameworkCompatible('{tfm1}', '{tfm2}'))");
+ }
+
+ private void AssertThrows(Expander expander, string expression, string expectedMessage)
+ {
+ var ex = Assert.Throws(
+ () => expander.ExpandPropertiesLeaveTypedAndEscaped(
expression,
ExpanderOptions.ExpandProperties,
- MockElementLocation.Instance);
+ MockElementLocation.Instance));
- Assert.Equal(expected, actual);
- }
+ Assert.Contains(expectedMessage, ex.Message);
+ }
+
+ private void AssertSuccess(Expander expander, object expected, string expression)
+ {
+ var actual = expander.ExpandPropertiesLeaveTypedAndEscaped(
+ expression,
+ ExpanderOptions.ExpandProperties,
+ MockElementLocation.Instance);
+
+ Assert.Equal(expected, actual);
}
///
diff --git a/src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj b/src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj
index 5806db2d3e6..c36a51b66b8 100644
--- a/src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj
+++ b/src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj
@@ -11,12 +11,17 @@
$(DefineConstants);NO_MSBUILDTASKHOST
+
+ true
+
+ all
+
diff --git a/src/Build/Evaluation/Expander.cs b/src/Build/Evaluation/Expander.cs
index 3242c693ab3..06b66765bd1 100644
--- a/src/Build/Evaluation/Expander.cs
+++ b/src/Build/Evaluation/Expander.cs
@@ -3916,6 +3916,30 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
return true;
}
}
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.GetTargetFrameworkIdentifier), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArg(args, out string arg0))
+ {
+ returnVal = IntrinsicFunctions.GetTargetFrameworkIdentifier(arg0);
+ return true;
+ }
+ }
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.GetTargetFrameworkVersion), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArg(args, out string arg0))
+ {
+ returnVal = IntrinsicFunctions.GetTargetFrameworkVersion(arg0);
+ return true;
+ }
+ }
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.IsTargetFrameworkCompatible), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArgs(args, out string arg0, out string arg1))
+ {
+ returnVal = IntrinsicFunctions.IsTargetFrameworkCompatible(arg0, arg1);
+ return true;
+ }
+ }
}
else if (_receiverType == typeof(Path))
{
diff --git a/src/Build/Evaluation/IntrinsicFunctions.cs b/src/Build/Evaluation/IntrinsicFunctions.cs
index 5ab70bf0ddf..55f9e185226 100644
--- a/src/Build/Evaluation/IntrinsicFunctions.cs
+++ b/src/Build/Evaluation/IntrinsicFunctions.cs
@@ -4,8 +4,6 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
-using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
@@ -32,6 +30,8 @@ internal static class IntrinsicFunctions
private static readonly Lazy RegistrySdkRegex = new Lazy(() => new Regex(@"^HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Microsoft SDKs\\Windows\\v(\d+\.\d+)$", RegexOptions.IgnoreCase));
#endif // FEATURE_WIN32_REGISTRY
+ private static readonly Lazy NuGetFramework = new Lazy(() => new NuGetFrameworkWrapper());
+
///
/// Add two doubles
///
@@ -480,6 +480,21 @@ internal static bool VersionLessThanOrEquals(string a, string b)
return SimpleVersion.Parse(a) <= SimpleVersion.Parse(b);
}
+ internal static string GetTargetFrameworkIdentifier(string tfm)
+ {
+ return NuGetFramework.Value.GetTargetFrameworkIdentifier(tfm);
+ }
+
+ internal static string GetTargetFrameworkVersion(string tfm)
+ {
+ return NuGetFramework.Value.GetTargetFrameworkVersion(tfm);
+ }
+
+ internal static bool IsTargetFrameworkCompatible(string target, string candidate)
+ {
+ return NuGetFramework.Value.IsCompatible(target, candidate);
+ }
+
public static string GetCurrentToolsDirectory()
{
return BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory;
diff --git a/src/Build/Microsoft.Build.csproj b/src/Build/Microsoft.Build.csproj
index c70ad9fc654..f90572b462b 100644
--- a/src/Build/Microsoft.Build.csproj
+++ b/src/Build/Microsoft.Build.csproj
@@ -154,6 +154,7 @@
+
diff --git a/src/Build/Resources/Strings.resx b/src/Build/Resources/Strings.resx
index 010deec0fb0..846868e1a22 100644
--- a/src/Build/Resources/Strings.resx
+++ b/src/Build/Resources/Strings.resx
@@ -1825,4 +1825,7 @@ Utilization: {0} Average Utilization: {1:###.0}
Property initial value: $({0})="{1}" Source: {2}
+
+ A required NuGet assembly was not found. Expected Path: {0}
+
\ No newline at end of file
diff --git a/src/Build/Resources/xlf/Strings.cs.xlf b/src/Build/Resources/xlf/Strings.cs.xlf
index f8af843e339..245e60f730e 100644
--- a/src/Build/Resources/xlf/Strings.cs.xlf
+++ b/src/Build/Resources/xlf/Strings.cs.xlf
@@ -122,6 +122,11 @@
Operaci nelze dokončit, protože funkce BeginBuild ještě nebyla zavolána.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: Uživatelem zadané zpětné volání ProjectInstanceFactoryFunc vrátilo odkaz null. To není přípustné.
diff --git a/src/Build/Resources/xlf/Strings.de.xlf b/src/Build/Resources/xlf/Strings.de.xlf
index ff9d8afd0de..ec4322d75e3 100644
--- a/src/Build/Resources/xlf/Strings.de.xlf
+++ b/src/Build/Resources/xlf/Strings.de.xlf
@@ -122,6 +122,11 @@
Der Vorgang kann nicht abgeschlossen werden, da BeginBuild noch nicht aufgerufen wurde.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: Ein benutzerseitig angegebener ProjectInstanceFactoryFunc-Rückruf hat einen NULL-Verweis zurückgegeben. Dies ist nicht zulässig.
diff --git a/src/Build/Resources/xlf/Strings.en.xlf b/src/Build/Resources/xlf/Strings.en.xlf
index 141c71a1f04..ca1dd2da57a 100644
--- a/src/Build/Resources/xlf/Strings.en.xlf
+++ b/src/Build/Resources/xlf/Strings.en.xlf
@@ -122,6 +122,11 @@
The operation cannot be completed because BeginBuild has not yet been called.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.
diff --git a/src/Build/Resources/xlf/Strings.es.xlf b/src/Build/Resources/xlf/Strings.es.xlf
index 51195540f5c..2c081aa56d0 100644
--- a/src/Build/Resources/xlf/Strings.es.xlf
+++ b/src/Build/Resources/xlf/Strings.es.xlf
@@ -122,6 +122,11 @@
La operación no se puede completar porque todavía no se llamó a BeginBuild.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: Se devolvió una referencia nula de una devolución de llamada de ProjectInstanceFactoryFunc proporcionada por el usuario, y no se permite.
diff --git a/src/Build/Resources/xlf/Strings.fr.xlf b/src/Build/Resources/xlf/Strings.fr.xlf
index 3d6c1cc1861..16a7024cede 100644
--- a/src/Build/Resources/xlf/Strings.fr.xlf
+++ b/src/Build/Resources/xlf/Strings.fr.xlf
@@ -122,6 +122,11 @@
Impossible d'effectuer l'opération car la méthode BeginBuild n'a pas encore été appelée.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: Une référence null a été retournée à partir d'un rappel ProjectInstanceFactoryFunc fourni par l'utilisateur. Ceci n'est pas autorisé.
diff --git a/src/Build/Resources/xlf/Strings.it.xlf b/src/Build/Resources/xlf/Strings.it.xlf
index 13e46cf8fba..7cf9c7da35c 100644
--- a/src/Build/Resources/xlf/Strings.it.xlf
+++ b/src/Build/Resources/xlf/Strings.it.xlf
@@ -122,6 +122,11 @@
Non è possibile completare l'operazione perché BeginBuild non è stato ancora chiamato.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: è stato restituito un riferimento Null da un callback ProjectInstanceFactoryFunc fornito dall'utente. Questa operazione non è consentita.
diff --git a/src/Build/Resources/xlf/Strings.ja.xlf b/src/Build/Resources/xlf/Strings.ja.xlf
index 57b78eab025..269832f4806 100644
--- a/src/Build/Resources/xlf/Strings.ja.xlf
+++ b/src/Build/Resources/xlf/Strings.ja.xlf
@@ -122,6 +122,11 @@
BeginBuild がまだ呼び出されていないため、操作を完了できません。
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: ユーザー提供の ProjectInstanceFactoryFunc コールバックから null 参照が返されました。これは許可されていません。
diff --git a/src/Build/Resources/xlf/Strings.ko.xlf b/src/Build/Resources/xlf/Strings.ko.xlf
index 56f87996e63..d969c555020 100644
--- a/src/Build/Resources/xlf/Strings.ko.xlf
+++ b/src/Build/Resources/xlf/Strings.ko.xlf
@@ -122,6 +122,11 @@
BeginBuild가 아직 호출되지 않았으므로 작업을 완료할 수 없습니다.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: 사용자가 제공한 ProjectInstanceFactoryFunc 콜백에서 Null 참조가 반환되었습니다. 이는 허용되지 않습니다.
diff --git a/src/Build/Resources/xlf/Strings.pl.xlf b/src/Build/Resources/xlf/Strings.pl.xlf
index f4d4a334239..01ed823e267 100644
--- a/src/Build/Resources/xlf/Strings.pl.xlf
+++ b/src/Build/Resources/xlf/Strings.pl.xlf
@@ -122,6 +122,11 @@
Nie można zakończyć operacji, ponieważ metoda BeginBuild nie została jeszcze wywołana.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: Z podanego przez użytkownika wywołania zwrotnego ProjectInstanceFactoryFunc została zwrócona pusta referencja. Jest to niedozwolone.
diff --git a/src/Build/Resources/xlf/Strings.pt-BR.xlf b/src/Build/Resources/xlf/Strings.pt-BR.xlf
index d89955e9761..1ebadba8527 100644
--- a/src/Build/Resources/xlf/Strings.pt-BR.xlf
+++ b/src/Build/Resources/xlf/Strings.pt-BR.xlf
@@ -122,6 +122,11 @@
A operação não pode ser concluída porque BeginBuild ainda não foi chamado.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: Uma referência nula foi devolvida de um retorno de chamada do ProjectInstanceFactoryFunc fornecido pelo usuário. Isso não é permitido.
diff --git a/src/Build/Resources/xlf/Strings.ru.xlf b/src/Build/Resources/xlf/Strings.ru.xlf
index 8adb28739fd..0e8728ed6ca 100644
--- a/src/Build/Resources/xlf/Strings.ru.xlf
+++ b/src/Build/Resources/xlf/Strings.ru.xlf
@@ -122,6 +122,11 @@
Не удается завершить операцию, так как ещё не был вызван BeginBuild.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: ссылка со значением NULL была возвращена из предоставленного пользователем вызова ProjectInstanceFactoryFunc. Это недопустимо.
diff --git a/src/Build/Resources/xlf/Strings.tr.xlf b/src/Build/Resources/xlf/Strings.tr.xlf
index 32881e71a8e..19de9e7a29a 100644
--- a/src/Build/Resources/xlf/Strings.tr.xlf
+++ b/src/Build/Resources/xlf/Strings.tr.xlf
@@ -122,6 +122,11 @@
BeginBuild henüz çağrılmadığı için işlem tamamlanamıyor.
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: Kullanıcı tarafından sağlanan bir ProjectInstanceFactoryFunc geri aramasında null başvuru var. Buna izin verilmez.
diff --git a/src/Build/Resources/xlf/Strings.zh-Hans.xlf b/src/Build/Resources/xlf/Strings.zh-Hans.xlf
index a2dafa5caa3..3b1f23c2414 100644
--- a/src/Build/Resources/xlf/Strings.zh-Hans.xlf
+++ b/src/Build/Resources/xlf/Strings.zh-Hans.xlf
@@ -122,6 +122,11 @@
无法完成该操作,因为尚未调用 BeginBuild。
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: 从用户提供的 ProjectInstanceFactoryFunc 回调中返回了一个空引用。这是不允许的。
diff --git a/src/Build/Resources/xlf/Strings.zh-Hant.xlf b/src/Build/Resources/xlf/Strings.zh-Hant.xlf
index 80a94bdb226..b8349400ff0 100644
--- a/src/Build/Resources/xlf/Strings.zh-Hant.xlf
+++ b/src/Build/Resources/xlf/Strings.zh-Hant.xlf
@@ -122,6 +122,11 @@
無法完成作業,因為尚未呼叫 BeginBuild。
+
+ A required NuGet assembly was not found. Expected Path: {0}
+ A required NuGet assembly was not found. Expected Path: {0}
+
+ MSB4253: A null reference was returned from a user-provided ProjectInstanceFactoryFunc callback. This is not allowed.MSB4253: 使用者提供的 ProjectInstanceFactoryFunc 回呼傳回了 null 參考。這是不允許的情況。
diff --git a/src/Build/Utilities/NuGetFrameworkWrapper.cs b/src/Build/Utilities/NuGetFrameworkWrapper.cs
new file mode 100644
index 00000000000..117e85acd93
--- /dev/null
+++ b/src/Build/Utilities/NuGetFrameworkWrapper.cs
@@ -0,0 +1,69 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.IO;
+using System.Reflection;
+using Microsoft.Build.Shared;
+
+namespace Microsoft.Build.Evaluation
+{
+ ///
+ /// Wraps the NuGet.Frameworks assembly, which is referenced by reflection.
+ ///
+ internal class NuGetFrameworkWrapper
+ {
+ ///
+ /// NuGet Types
+ ///
+ private static MethodInfo ParseMethod;
+ private static MethodInfo IsCompatibleMethod;
+ private static object DefaultCompatibilityProvider;
+ private static PropertyInfo FrameworkProperty;
+ private static PropertyInfo VersionProperty;
+
+ public NuGetFrameworkWrapper()
+ {
+ /// Resolve the location of the NuGet.Frameworks assembly
+ var assemblyDirectory = BuildEnvironmentHelper.Instance.Mode == BuildEnvironmentMode.VisualStudio ?
+ Path.Combine(BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory, "Common7", "IDE", "CommonExtensions", "Microsoft", "NuGet") :
+ BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory;
+ try
+ {
+ var NuGetAssembly = Assembly.LoadFile(Path.Combine(assemblyDirectory, "NuGet.Frameworks.dll"));
+ var NuGetFramework = NuGetAssembly.GetType("NuGet.Frameworks.NuGetFramework");
+ var NuGetFrameworkCompatibilityProvider = NuGetAssembly.GetType("NuGet.Frameworks.CompatibilityProvider");
+ var NuGetFrameworkDefaultCompatibilityProvider = NuGetAssembly.GetType("NuGet.Frameworks.DefaultCompatibilityProvider");
+ ParseMethod = NuGetFramework.GetMethod("Parse", new Type[] { typeof(string) });
+ IsCompatibleMethod = NuGetFrameworkCompatibilityProvider.GetMethod("IsCompatible");
+ DefaultCompatibilityProvider = NuGetFrameworkDefaultCompatibilityProvider.GetMethod("get_Instance").Invoke(null, new object[] { });
+ FrameworkProperty = NuGetFramework.GetProperty("Framework");
+ VersionProperty = NuGetFramework.GetProperty("Version");
+ }
+ catch
+ {
+ throw new InternalErrorException(string.Format(AssemblyResources.GetString("NuGetAssemblyNotFound"), assemblyDirectory));
+ }
+ }
+
+ private object Parse(string tfm)
+ {
+ return ParseMethod.Invoke(null, new object[] { tfm });
+ }
+
+ public string GetTargetFrameworkIdentifier(string tfm)
+ {
+ return FrameworkProperty.GetValue(Parse(tfm)) as string;
+ }
+
+ public string GetTargetFrameworkVersion(string tfm)
+ {
+ return (VersionProperty.GetValue(Parse(tfm)) as Version).ToString(2);
+ }
+
+ public bool IsCompatible(string target, string candidate)
+ {
+ return Convert.ToBoolean(IsCompatibleMethod.Invoke(DefaultCompatibilityProvider, new object[] { Parse(target), Parse(candidate) }));
+ }
+ }
+}