我想获取BindingSource连接或配置的项目的Type。 BindingSource.DataSource属性可以设置为对象,列表或类型。如果它是Type,则显然还没有绑定项,但是我仍然想获得Type。对于列表,我需要项目类型,而不是列表类型。
我目前具有实现IListItemType接口的业务对象的自定义列表类型,该接口是我为解决此问题而创建的。我现在想以一种更通用的方式使它工作,以便它可以与任何列表一起使用。
我已经通过API文档寻找了一种实现此目的的好方法,但是到目前为止,我还没有碰到任何运气。我是否正在丢失某些东西,或者这仅仅是我不能或不应该做的事情?
我最近在框架中遇到了ListBindingHelper类,该类具有我一直在寻找的所有内容:
System.Windows.Forms.ListBindingHelper.GetListItemType()
返回列表或集合中包含的项目的类型。
ListBindingHelper.GetListItemProperties()
返回描述列表中包含项的属性的PropertyDescriptorCollection。
没有完全通用的方法来获取列表的“类型”。最常见的方法是检查第一项,但这可能会产生误导,因为您可以在不太具体的集合中拥有more specific类型的对象(换句话说,该集合可能是List<object>
,但第一项可能是string
,导致您猜测它是List<string>
)。如果您确信所有元素都是相同的类型(意味着没有一个元素比集合的泛型类型或其他任何对象都更具体),那么检查第一个项目是最简单的。
此外,您可以使用GetType
检查列表的实际类型并检查其接口。可能是强类型化的[[any集合将实现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
。
我遇到了类似的问题。我的情况是BindingSource.DataSource将始终绑定到IEnumerable BUT,但列表中可能没有任何项目。事实证明BindingSource有一个称为“ itemType”的私有实例成员。该字段可以满足您的需求:如果BindingSource绑定到列表,则显示列表的元素类型;如果没有列表,则显示BindingSource绑定到的对象的类型。] >
为了访问该字段值,我使用了一些怪异的反思:
FieldInfo fi =
typeof(BindingSource)
.GetField("itemType", BindingFlags.NonPublic | BindingFlags.Instance);
Type myElementType = fi.GetValue(DataBinder.RestrictedDataBinding) as Type;
[没有做大量研究,我有点假设它所做的是显示innerList的元素类型,这就是为什么DataSource是否为列表类型都无关紧要的原因。另外,我假设此字段将准确显示BindingSource支持的任何类型的列表的元素类型(包括IQueryable等)。
警告:我没有对该字段进行太多测试,所以我不知道是否有某些情况使它无法读取正确的元素类型。例如,重置BindingSource的DataSource属性时,该字段是否总是准确地更新吗?如果将DataSource属性重置为具有不同elementType的列表怎么办?就我而言,这些例外和其他例外均不适用,但您可能需要对其进行测试。
最后,使用反射来侵入私有领域会破坏所有的oop原则。记在脑子里。另外,请记住,很可能会有一个很好的原因隐藏了itemType字段。如果您需要进一步研究,则BindingSource类的代码是公开可用的。