我想获取BindingSource连接或配置的项目类型。 BindingSource.DataSource属性可以设置为对象,列表或类型。如果它是一个Type,它显然还没有绑定项,但我仍然希望得到Type。对于List,我需要项目Type,而不是列表类型。
我目前有一个自定义列表类型,用于实现IListItemType接口的业务对象,我创建这个接口是为了解决这个问题。我现在想以更通用的方式使用它,以便它可以用于任何列表。
我已经查看了API文档以获得这样做的好方法,但到目前为止我还没有运气。我错过了什么,或者这只是我不能或不应该做的事情?
答案 0 :(得分:6)
我最近在框架中遇到了这个问题。
System.Windows.Forms.ListBindingHelper.GetListItemType()和GetListItemProperties()
这门课有我想要的一切。
答案 1 :(得分:2)
没有完全通用的方法来获取列表的“类型”。最常见的方法是检查第一项,但这可能会产生误导,因为您可以在不太具体的集合中拥有更具体类型的对象(换句话说,该集合可能是List<object>
,但第一项可能是string
,导致您猜测它是List<string>
)。如果您确信所有元素都是相同的类型(意味着没有比集合的泛型类型或任何其他对象更具体),那么检查第一个项目是最简单的。
除此之外,您可以使用GetType
检查列表的实际类型并检查其接口。有可能强类型的任何集合将实现IEnumerable<T>
,因此您可以迭代其接口寻找通用的IEnumerable
,然后查看其泛型类型参数。它(不仅仅是)一点点,但应该有效。
TL; DR版本
试试这个。假设您正在使用.NET 3.5并将列表存储在名为list
的变量中:
var listType = list.GetType().GetInterfaces()
.Where(t => t.Name == "IEnumerable" && t.IsGenericType)
.Select(t => t.GetGenericArguments()[0]).FirstOrDefault();
只要列表实现IEnumerable<T>
,这将为您提供T
。如果没有,则无论如何列表类型都可能是object
。
答案 2 :(得分:1)
自从这个答案出现以来已经有一段时间了,但万一有人还在寻找答案......
我遇到了类似的问题。我的场景是BindingSource.DataSource总是绑定到IEnumerable但是列表中可能没有任何项目。事实证明,BindingSource有一个名为&#34; itemType&#34;的私有实例成员。这个字段只是你正在寻找的东西:如果BindingSource绑定到列表,它显示列表的元素类型,或者如果没有列表,它显示BindingSource绑定的对象的类型
要访问字段值,我使用了一些hacky反射:
FieldInfo fi =
typeof(BindingSource)
.GetField("itemType", BindingFlags.NonPublic | BindingFlags.Instance);
Type myElementType = fi.GetValue(DataBinder.RestrictedDataBinding) as Type;
在没有做太多研究的情况下,我假设它正在做的是显示innerList的元素类型,这就是为什么DataSource是否是列表类型并不重要的原因。此外,我假设此字段将准确显示BindingSource支持的任何类型列表的元素类型(包括IQueryables等)。
警告:我没有对此字段进行过多次测试,因此我不知道是否存在导致其无法读取正确元素类型的情况。例如,当重置BindingSource的DataSource属性时,该字段是否始终准确更新?如果将DataSource属性重置为具有不同elementType的列表,该怎么办?在我的情况下,这些例外情况和其他例外情况并不适用,但您可能希望对其进行测试。
最后,使用反射入侵私有字段会破坏各种oop原则。记在脑子里。另外,请记住,很有可能是隐藏itemType字段的原因。如果您需要进一步调查,BindingSource类的代码是公开的。