gpt4 book ai didi

c# - 如何使用 .NET 反射检查可为空的引用类型

转载 作者:太空狗 更新时间:2023-10-29 23:35:52 28 4
gpt4 key购买 nike

C# 8.0 引入了可为空的引用类型。这是一个具有可为空属性的简单类:

public class Foo
{
public String? Bar { get; set; }
}

有没有办法通过反射检查类属性是否使用可为空的引用类型?

最佳答案

在 .NET 6 中,NullabilityInfoContext添加了 API 来处理此问题。参见 this answer .


在此之前,你需要自己去读取属性。这似乎有效,至少在我测试过的类型上是这样。

public static bool IsNullable(PropertyInfo property) =>
IsNullableHelper(property.PropertyType, property.DeclaringType, property.CustomAttributes);

public static bool IsNullable(FieldInfo field) =>
IsNullableHelper(field.FieldType, field.DeclaringType, field.CustomAttributes);

public static bool IsNullable(ParameterInfo parameter) =>
IsNullableHelper(parameter.ParameterType, parameter.Member, parameter.CustomAttributes);

private static bool IsNullableHelper(Type memberType, MemberInfo? declaringType, IEnumerable<CustomAttributeData> customAttributes)
{
if (memberType.IsValueType)
return Nullable.GetUnderlyingType(memberType) != null;

var nullable = customAttributes
.FirstOrDefault(x => x.AttributeType.FullName == "System.Runtime.CompilerServices.NullableAttribute");
if (nullable != null && nullable.ConstructorArguments.Count == 1)
{
var attributeArgument = nullable.ConstructorArguments[0];
if (attributeArgument.ArgumentType == typeof(byte[]))
{
var args = (ReadOnlyCollection<CustomAttributeTypedArgument>)attributeArgument.Value!;
if (args.Count > 0 && args[0].ArgumentType == typeof(byte))
{
return (byte)args[0].Value! == 2;
}
}
else if (attributeArgument.ArgumentType == typeof(byte))
{
return (byte)attributeArgument.Value! == 2;
}
}

for (var type = declaringType; type != null; type = type.DeclaringType)
{
var context = type.CustomAttributes
.FirstOrDefault(x => x.AttributeType.FullName == "System.Runtime.CompilerServices.NullableContextAttribute");
if (context != null &&
context.ConstructorArguments.Count == 1 &&
context.ConstructorArguments[0].ArgumentType == typeof(byte))
{
return (byte)context.ConstructorArguments[0].Value! == 2;
}
}

// Couldn't find a suitable attribute
return false;
}

参见 this document了解详情。

一般要点是属性本身可以有一个 [Nullable] 属性,或者如果没有,封闭类型可能有 [NullableContext]属性。我们首先查找 [Nullable],如果没有找到,我们会查找封闭类型的 [NullableContext]

编译器可能会将属性嵌入到程序集中,并且由于我们可能正在查看来自不同程序集的类型,因此我们需要进行仅反射加载。

[Nullable] 如果属性是通用的,则可以用数组实例化。在这种情况下,第一个元素代表实际属性(其他元素代表通用参数)。 [NullableContext] 总是用单个字节实例化。

2 的值表示“可为空”。 1 表示“不可为空”,0 表示“不经意”。

关于c# - 如何使用 .NET 反射检查可为空的引用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58453972/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com