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

发布于 2024-09-05 15:01:37 字数 296 浏览 9 评论 0原文

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

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

我已经浏览了 API 文档以寻找实现此目的的好方法,但到目前为止我还没有任何运气。我是否错过了什么,或者这只是我不能或不应该做的事情?

I would like to get the Type of item that a BindingSource is hooked up to or configured for. The BindingSource.DataSource property can be set to an object, list, or type. If it is a Type, it obviously does not have a bound item yet, but I would still like to get the Type. For a List, I need the item Type, not the list type.

I currently have a custom list type for business objects that implement an IListItemType interface, that I created to solve this problem a while back. I would now like to get this working in a more generic fashion so that it will work with any list.

I've looked through the API docs for for a good way to do this, but so far I have not had any luck. Am I missing something or is this just something I can not or should not be doing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

狼性发作 2024-09-12 15:01:37

我最近在框架中遇到了 ListBindingHelper 类,它拥有我正在寻找的一切:

System.Windows.Forms.ListBindingHelper.GetListItemType()

返回列表或集合中包含的项目的类型。

ListBindingHelper.GetListItemProperties()

返回一个 PropertyDescriptorCollection,它描述列表中包含的项目的属性。

I recently ran across the ListBindingHelper class in the framework that has everything I was looking for:

System.Windows.Forms.ListBindingHelper.GetListItemType()

Returns the type of an item contained in a list or collection.

ListBindingHelper.GetListItemProperties()

Returns a PropertyDescriptorCollection that describes the properties of the items contained in the list.

青瓷清茶倾城歌 2024-09-12 15:01:37

没有完全通用的方法来获取列表的“类型”。最常见的方法是检查第一项,但这可能会产生误导,因为您可以在不太具体的集合中拥有更具体类型的对象(换句话说,集合可能是 List,但第一项可能是 string,导致您猜测它是 List;)。如果您确信所有元素都是相同的类型(意味着没有一个元素比集合的通用类型或任何其他对象更具体),那么检查第一项是最简单的。

除此之外,您可以使用 GetType 检查列表的实际类型并检查其接口。 任何强类型集合都可能实现 IEnumerable,因此您可以迭代其接口,查找通用的 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。如果没有,列表类型很可能是 object

There is no completely generic way to get the "type" of the list. The most common method is to examine the first item, but this can be misleading as you can have objects that are of a more specific type in a collection that is less specific (in other words, the collection might be a List<object>, but the first item might be a string, leading you to guess that it's a List<string>). If you're confident that all of the elements will be the same type (meaning none are more specific than the generic type of the collection or than any of the other objects), then examining the first item is the easiest.

Apart from that, you could examine the list's actual type using GetType and check its interfaces. Chances are that any collection that's strongly typed is going to implement IEnumerable<T>, so you can iterate over its interfaces looking for IEnumerable that's generic, then look at its generic type arguments. It's (more than) a little hokey, but it should work.

TL;DR Version

Try this. Assuming you're using .NET 3.5 and have the list stored in a variable called list:

var listType = list.GetType().GetInterfaces()
              .Where(t => t.Name == "IEnumerable" && t.IsGenericType)
              .Select(t => t.GetGenericArguments()[0]).FirstOrDefault();

As long as the list implements IEnumerable<T>, this will give you T. If it doesn't, chances are the list type is object anyway.

梦毁影碎の 2024-09-12 15:01:37

自从这个答案出现以来已经有一段时间了,但以防万一有人仍在寻找答案......

我遇到了类似的问题。我的情况是 BindingSource.DataSource 将始终绑定到 IEnumerable 但列表中可能没有任何项目。事实证明,BindingSource 有一个名为“itemType”的私有实例成员。此字段正是您要查找的内容:如果 BindingSource 绑定到列表,它显示列表的元素类型;如果没有列表,它显示 BindingSource 绑定到的对象的类型。

为了访问字段值,我使用了一些 hacky 反射:

FieldInfo fi = 
    typeof(BindingSource)
    .GetField("itemType", BindingFlags.NonPublic | BindingFlags.Instance);
Type myElementType = fi.GetValue(DataBinder.RestrictedDataBinding) as Type;

在没有做太多研究的情况下,我假设它正在做的是显示 insideList 的元素类型,这就是为什么 DataSource 是列表类型还是列表类型并不重要。不是。另外,我假设该字段将准确显示 BindingSource 支持的任何类型列表的元素类型(包括 IQueryables 等)。

警告:我没有对该字段进行太多测试,所以我不知道是否存在会使其无法读取正确元素类型的情况。例如,当重置 BindingSource 的 DataSource 属性时,该字段是否总是能准确更新?如果 DataSource 属性重置为具有不同 elementType 的列表会怎样?就我而言,这些例外情况和其他例外情况并不适用,但您可能想测试它们。

最后,使用反射侵入私有字段违反了各种 oop 原则。请记住这一点。另外,请记住,隐藏 itemType 字段很可能是有充分理由的。如果您需要进一步调查,BindingSource 类的代码是公开可用的。

It's been quite a while since this answer has been on board but just in case anybody is still looking for the answer...

I ran into a similar problem. My scenario was that BindingSource.DataSource would always be bound to an IEnumerable BUT there may not be any items in the list. It turns out that BindingSource has a private instance member called "itemType". This field does just what you're looking for: it shows the element type of a list if the BindingSource is bound to a list, or it shows the type of the object that the BindingSource is bound to, if there is no list.

To access the field value, I used some hacky reflection:

FieldInfo fi = 
    typeof(BindingSource)
    .GetField("itemType", BindingFlags.NonPublic | BindingFlags.Instance);
Type myElementType = fi.GetValue(DataBinder.RestrictedDataBinding) as Type;

Without doing much research, I kind of assume that what it's doing is showing the element type of the innerList, which is why it doesn't matter if the DataSource is a list type or not. Also, I assume this field would accurately show the element type of any kind of list that is supported by the BindingSource (including IQueryables, etc.).

WARNING: I have NOT tested this field much so I don't know if there are cases that would make it not read the correct element type. For example, does the field always get accurately updated when the BindingSource's DataSource property is reset? What if the DataSource property is reset to a list that has a different elementType? In my case, these exceptions and others don't apply but you might want to test them.

Lastly, using reflection to hack into private fields breaks all kinds of oop principles. Keep that in mind. Also, keep in mind that there very well might be a good reason why the itemType field was hidden. If you need to investigate further, the code for the BindingSource class is publicly available.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文