Це, здається, працює, принаймні, на типи, з якими я його тестував.
Вам потрібно передати те, PropertyInfo
що вас цікавить, а також те, на Type
якому визначено вказане властивість ( не похідний або батьківський тип - він повинен бути точним типом):
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;
}
Докладніше див. У цьому документі .
Загальна суть полягає в тому, що або власне властивість може мати [Nullable]
атрибут на ньому, або, якщо це не тип анотації, що може містити [NullableContext]
атрибут. Спочатку ми шукаємо [Nullable]
, потім, якщо ми не знаходимо його, шукаємо [NullableContext]
на типі, що додається.
Компілятор може вбудувати атрибути в збірку, і оскільки ми можемо шукати тип з іншої збірки, нам потрібно виконати завантаження лише для відображення.
[Nullable]
може бути примірник масиву, якщо властивість є загальною. У цьому випадку перший елемент представляє фактичну властивість (а подальші елементи представляють загальні аргументи). [NullableContext]
завжди інстанціюється одним байтом.
Значення 2
означає "нульовий". 1
означає "не нульовий", а 0
означає "забутий".
[NullableContext(2), Nullable((byte) 0)]
до типу (Foo
) - так це на що потрібно перевірити, але мені потрібно більше копатись, щоб зрозуміти правила того, як це інтерпретувати!