![](/img/trans.png)
[英]Can I use packages written for .NET Framework in .NET Standard 2.0?
[英]How can I use CallerArgumentExpression with Visual Studio 2022 and .net Standard 2.0 or .net 4.8?
在 Visual Studio 2022 和 .net 6.0 中,我们有新的CallerArgumentExpression
属性,我们可以使用它来“捕获传递给方法的表达式,以在诊断/测试 API 中启用更好的错误消息并减少击键” 。
例如,我们可以编写一个 class 来检查 null 方法 arguments,如下所示:
public static class Contract
{
public static T RequiresArgNotNull<T>(T? item, [CallerArgumentExpression("item")] string? expression = default, string? message = null)
where T : class
{
if (item == null)
throw new ArgumentNullException(
expression ?? "<unknown>",
message ?? (expression != null ? "Requires " + expression + " != null" : "RequiresArgNotNull() failed."));
return item;
}
}
可以这样使用:
using static ClassLibrary1.Contract; // To allow just putting RequiresArgNotNull()
...
static void test(string theString)
{
RequiresArgNotNull(theString); // Note that we do NOT need to pass the parameter
// name as a separate string.
Console.WriteLine(theString);
}
如果theString
是 null,则会抛出如下所示的异常:
System.ArgumentNullException: Requires theString != null
Parameter name: theString
我希望能够将此功能与 .net 4.8 和/或 .net 标准 2.0 一起使用。 这可能吗?
如果您使用的是 Visual Studio 2022,则可以通过定义CallerArgumentExpressionAttribute
的本地internal
实现,将CallerArgumentExpression
与 .net 4.8 和/或 .net Standard 2.0 一起使用:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
internal sealed class CallerArgumentExpressionAttribute : Attribute
{
public CallerArgumentExpressionAttribute(string parameterName)
{
ParameterName = parameterName;
}
public string ParameterName { get; }
}
}
请注意,您必须使用System.Runtime.CompilerServices
命名空间才能使其正常工作。 通过使这个实现internal
,您可以保证它不会与任何系统定义的实现冲突。
这将编译为.net Standard 2.0
目标,因此它也可以被以.net 4.8
、 .net Core 3.1
为目标的程序集使用。
另请注意,您仍然需要 Visual Studio 2022 及其 SDK 才能工作 - 如果您尝试使用 Visual Studio 2019,它将编译正常,但参数将为 null。
您可以在使用CallerArgumentExpression
的程序集中包含上述 class ,它将按预期工作。
示例 .net 标准 2.0 class 库提供Contract.RequiresArgNotNull()
:
(为简洁起见,此示例程序集使用命名空间ClassLibrary1
。)
项目:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8</LangVersion>
</PropertyGroup>
</Project>
CallerArgumentExpression.cs:
namespace System.Runtime.CompilerServices
{
#if !NET6_0_OR_GREATER
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
internal sealed class CallerArgumentExpressionAttribute : Attribute
{
public CallerArgumentExpressionAttribute(string parameterName)
{
ParameterName = parameterName;
}
public string ParameterName { get; }
}
#endif
}
合同.cs:
using System;
using System.Runtime.CompilerServices;
#nullable enable
namespace ClassLibrary1
{
public static class Contract
{
public static T RequiresArgNotNull<T>(T? item, [CallerArgumentExpression("item")] string? expression = default, string? message = null)
where T : class
{
if (item == null)
throw new ArgumentNullException(
expression ?? "<unknown>",
message ?? (expression != null ? "Requires " + expression + " != null" : "RequiresArgNotNull() failed."));
return item;
}
}
}
演示使用RequiresArgNotNull()
的示例控制台应用程序:
using System;
using static ClassLibrary1.Contract;
#nullable enable
namespace Demo
{
class Program
{
static void Main()
{
try
{
test(null!);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
static void test(string theString)
{
RequiresArgNotNull(theString);
Console.WriteLine(theString);
}
}
}
这将 output 出现以下异常消息(对于我的特定构建):
System.ArgumentNullException: Requires theString != null
Parameter name: theString
at ClassLibrary1.Contract.RequiresArgNotNull[T](T item, String expression, String message) in E:\Test\cs9\ConsoleApp1\ClassLibrary1\Contract.cs:line 18
at Demo.Program.test(String theString) in E:\Test\cs9\ConsoleApp1\ConsoleApp1\Program.cs:line 25
at Demo.Program.Main() in E:\Test\cs9\ConsoleApp1\ConsoleApp1\Program.cs:line 14
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.