ICollection<T>我正在尝试从未知类型的类中获取所有属性。此外,类型 T(集合的类型)在编译时是未知的。首先我尝试过这种方法:
foreach (var property in entity.GetType().GetProperties())
{
if (typeof(ICollection).IsAssignableFrom(property.PropertyType) || typeof(ICollection<>).IsAssignableFrom(property.PropertyType))
{
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
但它不起作用(即使对于ICollection属性也评估为 false)。
我让它像这样工作:
foreach (var property in entity.GetType().GetProperties())
{
var getMethod = property.GetGetMethod();
var test = getMethod.Invoke(entity, null);
if (test is ICollection)
{
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
但我不想执行所有吸气剂。为什么第一段代码不起作用?如何ICollection在不执行所有 getter 的情况下查找属性?
事实证明,通过IsAssignableFrom检查,您无法确定该接口是否是另一个接口的派生:
Console.WriteLine(typeof(ICollection<>).IsAssignableFrom(typeof(ICollection<Int32>)));
Console.WriteLine(typeof(ICollection<Int32>).IsAssignableFrom(typeof(ICollection<>)));
Run Code Online (Sandbox Code Playgroud)
都会写false;
在这里的帮助很少的情况下,这是我能想到的最好的解决方案:
static IEnumerable<PropertyInfo> GetICollectionOrICollectionOfTProperties(this Type type)
{
// Get properties with PropertyType declared as interface
var interfaceProps =
from prop in type.GetProperties()
from interfaceType in prop.PropertyType.GetInterfaces()
where interfaceType.IsGenericType
let baseInterface = interfaceType.GetGenericTypeDefinition()
where (baseInterface == typeof(ICollection<>)) || (baseInterface == typeof(ICollection))
select prop;
// Get properties with PropertyType declared(probably) as solid types.
var nonInterfaceProps =
from prop in type.GetProperties()
where typeof(ICollection).IsAssignableFrom(prop.PropertyType) || typeof(ICollection<>).IsAssignableFrom(prop.PropertyType)
select prop;
// Combine both queries into one resulting
return interfaceProps.Union(nonInterfaceProps);
}
Run Code Online (Sandbox Code Playgroud)
这个解决方案可能会产生一些重复(这几乎不可能,但一定要使用Distinct),而且看起来不太好。
但它在具有接口返回类型和具体返回类型的属性的此类上运行良好:
class Collections
{
public List<Int32> ListTProp
{
get;
set;
}
public IDictionary<Int32, String> IDictionaryProp
{
get;
set;
}
public ICollection ICollectionProp
{
get;
set;
}
public ICollection<DateTime> IDateTimeCollectionProp
{
get;
set;
}
}
Run Code Online (Sandbox Code Playgroud)