创建规则以对参数属性强制执行默认值
Create a rule to enforce defaults on an Parameter attribute
我正在查看 CallerMemberName 属性。当您指定这样的方法时
public void TraceInfo(string propertyName, [CallerMemberName] string memberName)
我们收到一个编译时错误,指出
Parameter with caller info must have a default value
CallerMemberName 属性是密封的,我想强制使用这样的默认参数 class
如何在常规属性上执行相同的默认属性 class?
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
public sealed class DefaultEnforcedAttribute : Attribute
{
public DefaultEnforcedAttribute()
{
}
}
属性为 [CallerMemberName]
的参数必须是可选的。这允许您在调用方法时省略此参数。然后C#会自动用调用者成员名填充这个参数。
public void TraceInfo(string propertyName, [CallerMemberName] string memberName = null)
您不能在编译时强制执行此规则,因为这会涉及一些编译器魔术,但您可以在属性的代码中(例如在静态构造函数中)进行一些反射。您将不得不枚举类型及其方法。
像这样:
var faultyProps = assembly.GetTypes()
.SelectMany(t => t.GetMethods())
.SelectMany(m => m.GetParameters())
.Where(p => p.GetCustomAttribute<DefaultEnforcedAttribute>() != null && !p.IsOptional);
这些验证是在编译时完成的,因此,它们应该由编译器实现。
好消息是自编译器平台 Roslyn 诞生以来,您可以实现 visitors,这样您就可以使用您的自定义扩展 C# 编译器验证。
我会开始阅读这些其他问答以查看使用 Roslyn 检查内容的示例:
- How to check if a property is decorated with a custom attribute using Roslyn?
- How to get all properties that are anotated with some attribute?
此外,您应该阅读 Roslyn 的官方文档,特别是这篇文章:Getting Started C# Syntax Analysis. Also see C# and Visual Basic - Use Roslyn to Write a Live Code Analyzer for Your API
最后,您可能需要下载并安装 .NET Compiler Platform SDK。
方法 #2 适用于那些不喜欢必须在多台机器上安装 Visual Studio 扩展程序的人
另一种将作为项目构建的一部分集成的老派方法可以是 MSBuild 目标,调用在 C# 中实现的 MSBuild 任务,该任务可以加载使用 AfterTargets
属性构建的程序集在 <Target>
上,值为 "AfterBuild"
。它将如下所示:
<Target Name="EnforcePostCompilationRules" AfterTargets="AfterBuild">
<EnforceMethodParameterDefaultValue />
</Target>
该任务将加载整个程序集并使用反射查找所有类型,其方法具有使用某些属性的参数。如果某些参数具有强制执行默认参数值的属性,但参数 没有默认值,则会抛出构建错误,并显示一条有意义的消息,指出哪个方法未通过整个验证。
方法 #3:使用 NuGet 安装 Roslyn 扩展
也许您对 Roslyn 为您带来的更广泛的可能性感到兴奋。检查此问答,其中有人回答说安装 Visual Studio 扩展是可能的,将其包装为 NuGet 包:
- NuGet Package which installs a VSIX
我正在查看 CallerMemberName 属性。当您指定这样的方法时
public void TraceInfo(string propertyName, [CallerMemberName] string memberName)
我们收到一个编译时错误,指出
Parameter with caller info must have a default value
CallerMemberName 属性是密封的,我想强制使用这样的默认参数 class
如何在常规属性上执行相同的默认属性 class?
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
public sealed class DefaultEnforcedAttribute : Attribute
{
public DefaultEnforcedAttribute()
{
}
}
属性为 [CallerMemberName]
的参数必须是可选的。这允许您在调用方法时省略此参数。然后C#会自动用调用者成员名填充这个参数。
public void TraceInfo(string propertyName, [CallerMemberName] string memberName = null)
您不能在编译时强制执行此规则,因为这会涉及一些编译器魔术,但您可以在属性的代码中(例如在静态构造函数中)进行一些反射。您将不得不枚举类型及其方法。
像这样:
var faultyProps = assembly.GetTypes()
.SelectMany(t => t.GetMethods())
.SelectMany(m => m.GetParameters())
.Where(p => p.GetCustomAttribute<DefaultEnforcedAttribute>() != null && !p.IsOptional);
这些验证是在编译时完成的,因此,它们应该由编译器实现。
好消息是自编译器平台 Roslyn 诞生以来,您可以实现 visitors,这样您就可以使用您的自定义扩展 C# 编译器验证。
我会开始阅读这些其他问答以查看使用 Roslyn 检查内容的示例:
- How to check if a property is decorated with a custom attribute using Roslyn?
- How to get all properties that are anotated with some attribute?
此外,您应该阅读 Roslyn 的官方文档,特别是这篇文章:Getting Started C# Syntax Analysis. Also see C# and Visual Basic - Use Roslyn to Write a Live Code Analyzer for Your API
最后,您可能需要下载并安装 .NET Compiler Platform SDK。
方法 #2 适用于那些不喜欢必须在多台机器上安装 Visual Studio 扩展程序的人
另一种将作为项目构建的一部分集成的老派方法可以是 MSBuild 目标,调用在 C# 中实现的 MSBuild 任务,该任务可以加载使用 AfterTargets
属性构建的程序集在 <Target>
上,值为 "AfterBuild"
。它将如下所示:
<Target Name="EnforcePostCompilationRules" AfterTargets="AfterBuild">
<EnforceMethodParameterDefaultValue />
</Target>
该任务将加载整个程序集并使用反射查找所有类型,其方法具有使用某些属性的参数。如果某些参数具有强制执行默认参数值的属性,但参数 没有默认值,则会抛出构建错误,并显示一条有意义的消息,指出哪个方法未通过整个验证。
方法 #3:使用 NuGet 安装 Roslyn 扩展
也许您对 Roslyn 为您带来的更广泛的可能性感到兴奋。检查此问答,其中有人回答说安装 Visual Studio 扩展是可能的,将其包装为 NuGet 包:
- NuGet Package which installs a VSIX