我可以从BindingSource获取项目类型吗?

时间:2010-06-14 19:06:34

标签: c# vb.net winforms bindingsource

我想获取BindingSource连接或配置的项目类型。 BindingSource.DataSource属性可以设置为对象,列表或类型。如果它是一个Type,它显然还没有绑定项,但我仍然希望得到Type。对于List,我需要项目Type,而不是列表类型。

我目前有一个自定义列表类型,用于实现IListItemType接口的业务对象,我创建这个接口是为了解决这个问题。我现在想以更通用的方式使用它,以便它可以用于任何列表。

我已经查看了API文档以获得这样做的好方法,但到目前为止我还没有运气。我错过了什么,或者这只是我不能或不应该做的事情?

3 个答案:

答案 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类的代码是公开的。