Dun*_*imu 5 .net c# .net-core c#-8.0 nullable-reference-types
我有使用 C#-8 并启用可为 null 类型的 .NET Core 项目。
我有以下课程
public class MyClass
{
public int? NullableInt { get; private set; }
public string? NullableString { get; private set; }
public string NonNullableString { get; private set; }
public MySubClass? MyNullableSubClass { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
我需要能够循环遍历类的所有属性并确定哪些属性可为空。
所以我的代码看起来像这样
public IEnumerable<string> GetNullableProperties(Type type)
{
var nullableProperties = new List<string>();
foreach (var property in type.GetProperties())
{
var isNullable = false;
if (property.PropertyType.IsValueType)
{
isNullable = Nullable.GetUnderlyingType(property.PropertyType) != null;
} else {
var nullableAttribute = property.PropertyType.CustomAttributes
.FirstOrDefault(a => a.AttributeType.Name == "NullableAttribute");
isNullable = nullableAttribute != null;
}
if (isNullable)
{
nullableProperties.Add(property.propertyType.Name)
}
}
return nullableProperties;
}
Run Code Online (Sandbox Code Playgroud)
将 的类型传递MyClass给此方法会返回["NullableInt", "NullableString", "NonNullableString", "MyNullableSubClass"]。
但是,预期返回值为["NullableInt", "NullableString", "MyNullableSubClass"]。
该属性之所以NonNullableString被确定为可为空,是因为它具有 Nullable 属性。
我的理解是,在判断引用类型是否可为空时,需要检查它是否具有 Nullable 属性。然而,字符串类型似乎并非如此。似乎所有字符串都定义了 nullable 属性。有没有办法找出 a 是否string可为空(即用可为空运算符定义?)。
我想出了完整的解决方案。我们需要检查属性和类上的自定义属性。
...
private const byte NonNullableContextValue = 1;
private const byte NullableContextValue = 2;
public IEnumerable<string> GetNullableProperties(Type type)
{
foreach (var property in type.GetProperties())
{
var isNullable = property.PropertyType.IsValueType
? Nullable.GetUnderlyingType(property.PropertyType) != null;
: IsReferenceTypePropertyNullable(property);
if (isNullable)
{
nullableProperties.Add(property.propertyType.Name)
}
}
return nullableProperties;
}
private function bool IsReferenceTypePropertyNullable(PropertyInfo property)
{
var classNullableContextAttribute = property.DeclaringType.CustomerProperties
.FirstOrDefault(c => c.AttributeType.Name == "NullableContextAttribute")
var classNullableContext = classNullableContextAttribute
?.ConstructorArguments
.First(ca => ca.ArgumentType.Name == "Byte")
.Value;
// EDIT: This logic is not correct for nullable generic types
var propertyNullableContext = property.CustomAttributes
.FirstOrDefault(c => c.AttributeType.Name == "NullableAttribute")
?.ConstructorArguments
.First(ca => ca.ArgumentType.Name == "Byte")
.Value;
// If the property does not have the nullable attribute then it's
// nullability is determined by the declaring class
propertyNullableContext ??= classNullableContext;
// If NullableContextAttribute on class is not set and the property
// does not have the NullableAttribute, then the proeprty is non nullable
if (propertyNullableContext == null)
{
return true;
}
// nullableContext == 0 means context is null oblivious (Ex. Pre C#8)
// nullableContext == 1 means not nullable
// nullableContext == 2 means nullable
switch (propertyNullableContext)
{
case NonNullableContextValue:
return false;
case NullableContextValue:
return true;
default:
throw new Exception("My error message");
}
}
Run Code Online (Sandbox Code Playgroud)
以下是有关可为空上下文值的一些信息:https://www.postsharp.net/blog/post/PostSharp-internals-handling-csharp-8-nullable-reference-types
| 归档时间: |
|
| 查看次数: |
1820 次 |
| 最近记录: |