使用反射我们如何判断 class 属性 是否为可空集合并获取其数据类型?
Using reflection how can we tell if a class property is a nullable collection and get its data type?
I have no problems with properties that are non-nullable collections but everything changes when the property is a nullable collection...
给定一个 class 具有可为空的集合属性(int?[], long?[], List, ...)
public class SomeClass
{
public int?[] PropertyX { get; set; }
public long?[] PropertyY { get; set; }
public float?[] PropertyZ { get; set; }
public List<decimal?> PropertyList { get; set; }
public string Name { get; set; }
}
如何判断 属性 是否为可为 null 的集合?
可为 null 的集合是否有 任何实际值?
最后,可空集合数据类型是什么?
public class SomeOtherClass
{
public string Discover(SomeClass someClass)
{
var sb = new StringBuilder();
foreach (var propertyInfo in someClass.GetType().GetProperties())
{
var propValue = propertyInfo.GetValue(someClass, new object[] { });
if (propValue.IsNullableCollection() && propValue.HasValue())
{
sb.AppendFormat("{0} data type is {1}", propValue.GetDataType());
}
}
return sb.ToString();
}
}
示例:
void Main
{
var sc = new SomeClass()
{
PropertyX = new int?[2]{50,10}
};
var output = new SomeOtherClass().Discover(sc);
//Display Output ...
}
"PropertyX has values and data type is int."
我写了一个方法,应该可以为您提供完成任务所需的所有工具:
public static void Discover(Type mainType)
{
foreach (var pi in mainType.GetProperties())
{
var t = pi.PropertyType;
if (t.IsArray)
{
(var isNullable, var innerT) = ExamineForNullable(t.GetElementType());
Console.WriteLine($"{pi.Name} data type is an array of {innerT} (nullable: {isNullable})");
}
else if (t.GetInterface(nameof(ICollection)) != null)
{
//TODO this is true for dictionaries too!
if (t.IsGenericType)
{
(var isNullable, var innerT) = ExamineForNullable(t.GetGenericArguments()[0]);
Console.WriteLine($"{pi.Name} data type is collection of {innerT} (nullable: {isNullable})");
}
else
{
//TODO
}
}
else
{
Console.WriteLine($"{pi.Name} data type is {t}");
}
}
}
static (bool nullable, Type type) ExamineForNullable(Type t)
=> t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)
? (true, Nullable.GetUnderlyingType(t))
: (false, t);
让我们 运行 使用以下 class,这是您示例 class 的修改版本:
public class SomeClass
{
public int?[] PropertyX { get; set; }
public List<decimal?> List1 { get; set; }
public List<decimal> List2 { get; set; }
public string Name { get; set; }
public Dictionary<string, decimal?> Dictionary { get; set; }
}
(...)
Discover(typeof(SomeClass));
请注意,您不需要 class 的对象来检查类型:Discover( new SomeClass())
与 Discover(typeof(SomeClass)
。
输出为:
PropertyX data type is an array of System.Int32 (nullable: True)
List1 data type is collection of System.Decimal (nullable: True)
List2 data type is collection of System.Decimal (nullable: False)
Name data type is System.String
Dictionary data type is collection of System.String (nullable: False)
I have no problems with properties that are non-nullable collections but everything changes when the property is a nullable collection...
给定一个 class 具有可为空的集合属性(int?[], long?[], List
public class SomeClass
{
public int?[] PropertyX { get; set; }
public long?[] PropertyY { get; set; }
public float?[] PropertyZ { get; set; }
public List<decimal?> PropertyList { get; set; }
public string Name { get; set; }
}
如何判断 属性 是否为可为 null 的集合?
可为 null 的集合是否有 任何实际值?
最后,可空集合数据类型是什么?
public class SomeOtherClass
{
public string Discover(SomeClass someClass)
{
var sb = new StringBuilder();
foreach (var propertyInfo in someClass.GetType().GetProperties())
{
var propValue = propertyInfo.GetValue(someClass, new object[] { });
if (propValue.IsNullableCollection() && propValue.HasValue())
{
sb.AppendFormat("{0} data type is {1}", propValue.GetDataType());
}
}
return sb.ToString();
}
}
示例:
void Main
{
var sc = new SomeClass()
{
PropertyX = new int?[2]{50,10}
};
var output = new SomeOtherClass().Discover(sc);
//Display Output ...
}
"PropertyX has values and data type is int."
我写了一个方法,应该可以为您提供完成任务所需的所有工具:
public static void Discover(Type mainType)
{
foreach (var pi in mainType.GetProperties())
{
var t = pi.PropertyType;
if (t.IsArray)
{
(var isNullable, var innerT) = ExamineForNullable(t.GetElementType());
Console.WriteLine($"{pi.Name} data type is an array of {innerT} (nullable: {isNullable})");
}
else if (t.GetInterface(nameof(ICollection)) != null)
{
//TODO this is true for dictionaries too!
if (t.IsGenericType)
{
(var isNullable, var innerT) = ExamineForNullable(t.GetGenericArguments()[0]);
Console.WriteLine($"{pi.Name} data type is collection of {innerT} (nullable: {isNullable})");
}
else
{
//TODO
}
}
else
{
Console.WriteLine($"{pi.Name} data type is {t}");
}
}
}
static (bool nullable, Type type) ExamineForNullable(Type t)
=> t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)
? (true, Nullable.GetUnderlyingType(t))
: (false, t);
让我们 运行 使用以下 class,这是您示例 class 的修改版本:
public class SomeClass
{
public int?[] PropertyX { get; set; }
public List<decimal?> List1 { get; set; }
public List<decimal> List2 { get; set; }
public string Name { get; set; }
public Dictionary<string, decimal?> Dictionary { get; set; }
}
(...)
Discover(typeof(SomeClass));
请注意,您不需要 class 的对象来检查类型:Discover( new SomeClass())
与 Discover(typeof(SomeClass)
。
输出为:
PropertyX data type is an array of System.Int32 (nullable: True)
List1 data type is collection of System.Decimal (nullable: True)
List2 data type is collection of System.Decimal (nullable: False)
Name data type is System.String
Dictionary data type is collection of System.String (nullable: False)