如何检查我的未初始化变量是否为 List 类型?
How do I check if my uninitialized variable is of type List?
我有以下 class 定义:
[ActionsClass[typeof(MyActions)]
public class NkProject
{
int ProjectId;
IList<NkItem> Items;
NkItem SingleItem;
}
class 主要只包含字段,class 属性说明哪个 class 负责 "handling" 这个 class 作为更大的一部分框架。
使用反射,我解析这个文件以生成一些元数据,我想知道 "Items" 是否属于 List 类型(或任何类型的充当列表的集合),但我的所有内容到目前为止我试过失败了。我正在遍历 FieldInfo[]
个对象的数组。
检查 IEnumerable
:
if(field.FieldType.GetInterface("IEnumerable") != null)
这还将字符串检测为 IEnumerables,这是不正确的。如果字符串未能通过此检查并在某种意义上被视为基元(上述 if
的 else
),我更愿意。
上面更改为:if(field is ICollection)
也失败了。
上面改成:if(field is IList && field.GetType().IsGenericType)
还是没能正确检测到
有没有办法只查看变量引用的类型来确定 Items
是否属于 List 类型并且对 string Items
的并行检查失败?我猜上面的 #2 和 #3 失败了,因为 Items
不是对象,因此没有任何继承信息附加到它。我可能是错的,但我认为这就是正在发生的事情。 A field.GetType().Name
returns 类型为 IList`1。不确定如何解决这个问题。
EDIT/UPDATE:如果上述检查失败,并且字符串通过,则输出元格式不正确。因为,如果它是 collection/list 个项目,我需要为它们获取更多元数据(通过适当设置的属性)。仅当变量的类型为 List/Collection 时才会执行此步骤,但如果它是单个引用或基元则不会执行。
反射码:
foreach (var field in fieldInfo)
{
Property property;
//If it's a collection field, get the appropriate collection name as set in its attribute
if (field.FieldType.GetInterface("IEnumerable") != null) //currently lets strings pass through too.
{
//Get the type of the "type argument" of the IEnumerable
Type[] typeArgs = field.FieldType.GetGenericArguments();
//Get the collection name for that type to use in the XML
MyAttribute att = (MyAttribute )Attribute.GetCustomAttribute(typeArgs[0], typeof(MyAttribute ));
if (att == null)
throw new ArgumentException("Using collection: {0} in Your class: {1}. Collection must have MyAttribute[Collection=\"\"] attribute defined on its class declaration.");
else
{
//do something with meta data
}
}
//If non-collection, possibly primitive field do something else
else
{
//do other stuff here.
}
}
您可以使用泛型类型信息来检查它是否是一个列表
if(field.FieldType.IsGenericType
&& field.FieldType.GetGenericTypeDefinition() == typeof(List<>))
目前我的代码库中有以下针对此类情况的函数。
public static bool Closes(this Type type, Type openType)
{
if (type == null)
return false;
if (type.IsGenericType && type.GetGenericTypeDefinition() == openType) return true;
foreach (var @interface in type.GetInterfaces())
{
if (@interface.Closes(openType)) return true;
}
return type.BaseType.Closes(openType);
}
这样你就可以调用
field.FieldType.Closes(typeof(List<>)
你可以试试这个方法:
public bool IsGenericList(Type type)
{
if (type == null)
return false;
if (!type.IsGenericType)
return false;
var genericArguments = type.GetGenericArguments();
if (genericArguments.Length != 1)
return false;
var listType = typeof(IList<>).MakeGenericType(genericArguments);
return listType.IsAssignableFrom(type);
}
我有以下 class 定义:
[ActionsClass[typeof(MyActions)]
public class NkProject
{
int ProjectId;
IList<NkItem> Items;
NkItem SingleItem;
}
class 主要只包含字段,class 属性说明哪个 class 负责 "handling" 这个 class 作为更大的一部分框架。
使用反射,我解析这个文件以生成一些元数据,我想知道 "Items" 是否属于 List 类型(或任何类型的充当列表的集合),但我的所有内容到目前为止我试过失败了。我正在遍历 FieldInfo[]
个对象的数组。
检查
IEnumerable
:if(field.FieldType.GetInterface("IEnumerable") != null)
这还将字符串检测为 IEnumerables,这是不正确的。如果字符串未能通过此检查并在某种意义上被视为基元(上述
if
的else
),我更愿意。上面更改为:
if(field is ICollection)
也失败了。上面改成:
if(field is IList && field.GetType().IsGenericType)
还是没能正确检测到
有没有办法只查看变量引用的类型来确定 Items
是否属于 List 类型并且对 string Items
的并行检查失败?我猜上面的 #2 和 #3 失败了,因为 Items
不是对象,因此没有任何继承信息附加到它。我可能是错的,但我认为这就是正在发生的事情。 A field.GetType().Name
returns 类型为 IList`1。不确定如何解决这个问题。
EDIT/UPDATE:如果上述检查失败,并且字符串通过,则输出元格式不正确。因为,如果它是 collection/list 个项目,我需要为它们获取更多元数据(通过适当设置的属性)。仅当变量的类型为 List/Collection 时才会执行此步骤,但如果它是单个引用或基元则不会执行。
反射码:
foreach (var field in fieldInfo)
{
Property property;
//If it's a collection field, get the appropriate collection name as set in its attribute
if (field.FieldType.GetInterface("IEnumerable") != null) //currently lets strings pass through too.
{
//Get the type of the "type argument" of the IEnumerable
Type[] typeArgs = field.FieldType.GetGenericArguments();
//Get the collection name for that type to use in the XML
MyAttribute att = (MyAttribute )Attribute.GetCustomAttribute(typeArgs[0], typeof(MyAttribute ));
if (att == null)
throw new ArgumentException("Using collection: {0} in Your class: {1}. Collection must have MyAttribute[Collection=\"\"] attribute defined on its class declaration.");
else
{
//do something with meta data
}
}
//If non-collection, possibly primitive field do something else
else
{
//do other stuff here.
}
}
您可以使用泛型类型信息来检查它是否是一个列表
if(field.FieldType.IsGenericType
&& field.FieldType.GetGenericTypeDefinition() == typeof(List<>))
目前我的代码库中有以下针对此类情况的函数。
public static bool Closes(this Type type, Type openType)
{
if (type == null)
return false;
if (type.IsGenericType && type.GetGenericTypeDefinition() == openType) return true;
foreach (var @interface in type.GetInterfaces())
{
if (@interface.Closes(openType)) return true;
}
return type.BaseType.Closes(openType);
}
这样你就可以调用
field.FieldType.Closes(typeof(List<>)
你可以试试这个方法:
public bool IsGenericList(Type type)
{
if (type == null)
return false;
if (!type.IsGenericType)
return false;
var genericArguments = type.GetGenericArguments();
if (genericArguments.Length != 1)
return false;
var listType = typeof(IList<>).MakeGenericType(genericArguments);
return listType.IsAssignableFrom(type);
}