[c#] .NET 리플렉션을 사용하여 nullable 참조 유형을 확인하는 방법

C # 8.0에는 nullable 참조 형식이 도입되었습니다. nullable 속성을 가진 간단한 클래스는 다음과 같습니다.

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

리플렉션을 통해 클래스 속성에서 nullable 참조 유형을 사용하는지 확인하는 방법이 있습니까?



답변

이것은 적어도 테스트 한 유형에서 작동하는 것으로 보입니다.

당신은을 전달해야 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의미하고 “명백하지 않음”을 의미합니다.


답변