Điều này dường như hoạt động, ít nhất là trên các loại tôi đã thử nghiệm nó.
Bạn cần chuyển PropertyInfo
cho thuộc tính mà bạn quan tâm và cả thuộc tính Type
mà tài sản đó được xác định ( không phải là loại có nguồn gốc hoặc loại gốc - nó phải là loại chính xác):
public static bool IsNullable(Type enclosingType, PropertyInfo property)
{
if (!enclosingType.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly).Contains(property))
throw new ArgumentException("enclosingType must be the type which defines property");
var nullable = property.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;
}
}
var context = enclosingType.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;
}
Xem tài liệu này để biết chi tiết.
Ý chính chung là bản thân [Nullable]
thuộc tính có thể có một thuộc tính trên nó hoặc nếu nó không có loại kèm theo có thể có [NullableContext]
thuộc tính. Trước tiên chúng tôi tìm kiếm [Nullable]
, sau đó nếu chúng tôi không tìm thấy nó, chúng tôi sẽ tìm [NullableContext]
loại kèm theo.
Trình biên dịch có thể nhúng các thuộc tính vào trong cụm và vì chúng ta có thể đang xem một loại từ một cụm khác, nên chúng ta cần thực hiện tải chỉ phản xạ.
[Nullable]
có thể được khởi tạo với một mảng, nếu thuộc tính là chung. Trong trường hợp này, phần tử đầu tiên đại diện cho thuộc tính thực tế (và các phần tử khác đại diện cho các đối số chung). [NullableContext]
luôn luôn được khởi tạo với một byte đơn.
Một giá trị 2
có nghĩa là "nullable". 1
có nghĩa là "không thể rỗng" và 0
có nghĩa là "không biết gì".
[NullableContext(2), Nullable((byte) 0)]
vào loại (Foo
) - vì vậy đó là những gì cần kiểm tra, nhưng tôi cần phải đào sâu hơn để hiểu các quy tắc về cách diễn giải điều đó!