[英]C# stop custom attribute from being applied to class
我在 C# 中创建了一个自定义属性:
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class ExampleAttribute : Attribute
{
}
我希望这仅适用于属性,但更具体地说,不是类(只是基本类型)的属性。
例子:
public class ExamplePoco
{
// These should be fine...
[Example]
public string Prop1 { get; set; }
[Example]
public bool Prop2 { get; set; }
[Example]
public int Prop3 { get; set; }
// But this shouldn't be allowed because it's a class, rather than base type
[Example]
public OtherExample Prop4 { get; set; }
}
public class OtherExample
{
public string Other1 { get; set; }
}
有谁知道我如何在编译时进一步限制这个自定义属性? 如果这只能在运行时完成,那么解决这个问题的最佳方法是什么?
提前致谢!
在编译时使用直接 C# 可以强制执行的数量是有限的。 正如评论中指出的那样,您可以编写自定义 Roslyn 扩展来查找无效使用。 这是一个相当繁重的解决方案 - 大多数人倾向于在运行时而不是在编译时实现对这类事情的验证。
想到的一些例子是 Newtonsoft 的JsonConverter
属性,它要求构造函数中的类型实现特定的接口,或者 Asp.Net 的Route
属性,它对语法和歧义有限制。 这些东西可以作为 Roslyn 扩展来实现,但最常见的约定是在运行时进行验证。
Eager Validation是您声明所有需要验证的类型(或约定)的地方,验证会立即完成。 为此声明类型的一些方法包括:
Type
的显式列表传递给Validate
方法惰性验证是您仅在使用类型时对其进行验证的地方。 这具有启动时间更快的优点,但这也意味着任何具有无效属性使用的类型在使用之前都不会被检测到。
验证使用反射,并且可能会对性能造成很大影响,因此如果您决定进行延迟验证,则绝对应该缓存结果。
为了验证类型是否具有不正确的属性使用,您可以创建如下方法:
private static readonly Type[] PrimitiveTypes = new Type[]
{
typeof(string),
typeof(int),
typeof(bool),
typeof(int?), // Are nullable primitive types allowed? You decide
}
public static void Validate(Type type)
{
var properties = type.GetProperties();
foreach (var property in properties)
{
var attribute = property.GetCustomAttribute<ExampleAttribute>();
if (attribute == null)
continue;
if (!Array.Contains(PrimitiveTypes, property.PropertyType))
throw new Exception("Make a custom exception type and message for this scenario");
}
}
在这个例子中,如果验证失败,我会抛出一个异常,只是为了简单起见。 如果您创建一个验证错误列表并返回它们,这对调试会很有帮助,这样用户就可以看到所有错误,而不仅仅是第一个错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.