如何使用.NET反射检查可为空的引用类型 [英] How to use .NET reflection to check for nullable reference type

查看:219
本文介绍了如何使用.NET反射检查可为空的引用类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

C# 8.0 introduces nullable reference types. Here's a simple class with a nullable property:

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

有没有一种方法可以通过反射来检查类属性是否使用可为空的引用类型?

Is there a way to check a class property uses a nullable reference type via reflection?

推荐答案

这似乎有效,至少在我测试过的类型上有效.

This appears to work, at least on the types I've tested it with.

您需要将PropertyInfo传递给您感兴趣的属性,并传递该属性在其上定义的Type(不是派生或父类型-它必须是确切的类型):

You need to pass the PropertyInfo for the property you're interested in, and also the Type which that property is defined on (not a derived or parent type - it has to be the exact 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;
}

有关详细信息,请参见本文档.

See this document for details.

一般的要点是,属性本身可以具有[Nullable]属性,或者如果属性本身不具有[NullableContext]属性,则它可以具有[NullableContext]属性.我们首先寻找[Nullable],然后如果找不到它,就在封闭类型中寻找[NullableContext].

The general gist is that either the property itself can have a [Nullable] attribute on it, or if it doesn't the enclosing type might have [NullableContext] attribute. We first look for [Nullable], then if we don't find it we look for [NullableContext] on the enclosing type.

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

The compiler might embed the attributes into the assembly, and since we might be looking at a type from a different assembly, we need to do a reflection-only load.

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

[Nullable] might be instantiated with an array, if the property is generic. In this case, the first element represents the actual property (and further elements represent generic arguments). [NullableContext] is always instantiated with a single byte.

2表示可为空". 1表示不可为空",0表示不为人所知".

A value of 2 means "nullable". 1 means "not nullable", and 0 means "oblivious".

这篇关于如何使用.NET反射检查可为空的引用类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆