我试图从未知类型的类中获取所有ICollection<T>
属性。另外,类型T(集合的类型)在编译时是未知的。首先,我尝试了这种方法:
foreach (var property in entity.GetType().GetProperties())
{
if (typeof(ICollection).IsAssignableFrom(property.PropertyType) || typeof(ICollection<>).IsAssignableFrom(property.PropertyType))
{
// do something
}
}
,但它不工作(评估false即使ICollection
属性)。
我让它像这样工作:
foreach (var property in entity.GetType().GetProperties())
{
var getMethod = property.GetGetMethod();
var test = getMethod.Invoke(entity, null);
if (test is ICollection)
{
// do something
}
}
,但我不想执行所有getter。为什么第一段代码不能正常工作?我怎么能找到ICollection
属性不执行所有getter ?
事实证明,使用IsAssignableFrom检查你无法发现接口是否是另一个接口的派生:
Console.WriteLine(typeof(ICollection<>).IsAssignableFrom(typeof(ICollection<Int32>)));
Console.WriteLine(typeof(ICollection<Int32>).IsAssignableFrom(typeof(ICollection<>)));
将同时写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);
}
这个解决方案可能会产生一些重复(这几乎是不可能的,但要确保使用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;
}
}
在尝试使用可接受的答案后,我遇到了只返回部分匹配的情况。我的对象有3个ICollection<T>
属性,我只返回了2个。我花了一些时间进行测试,试图找出原因,但我继续写下去:
public static IEnumerable<PropertyInfo> GetICollectionProperties(object entity)
{
return entity.GetType().GetProperties()
.Where(p => p.PropertyType.IsGenericType
&& p.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>));
}
我已经用相同的测试用例进行了测试,并且我从这个方法返回了正确的结果。
这将不会拾取非泛型集合,但是OP确实要求ICollection<T>
属性,尽管它可以很容易地重构以包含。它也不会返回不完全属于ICollection类型的属性(即,Eugene的List和字典在他的测试用例中不会返回(但再次,OP想要的))。