2010-06-14 2 views
3

Я хотел бы получить тип элемента, к которому подключен BindingSource или настроен для него. Свойство BindingSource.DataSource может быть установлено как объект, список или тип. Если это тип, у него явно нет связанного элемента, но я все равно хотел бы получить Type. Для списка мне нужен тип Item, а не тип списка.Могу ли я получить тип элемента из BindingSource?

В настоящее время у меня есть собственный тип списка для бизнес-объектов, которые реализуют интерфейс IListItemType, который я создал для решения этой проблемы некоторое время назад. Теперь я хотел бы, чтобы эта работа была более общей, чтобы она работала с любым списком.

Я просмотрел документы API для хорошего способа сделать это, но до сих пор мне не повезло. Я что-то упускаю или это то, чего я не могу или не должен делать?

+0

Проверьте этот вопрос: http://stackoverflow.com/questions/557340/c-generic-list-t-how-to-get-the-type-of-t –

+0

@Mikael: Этот вопрос не " t, похоже, связаны; этот вопрос звучит так, как будто он имеет дело со списком * вне * класса, а не * внутри *. –

ответ

6

Я недавно проверил это в рамке.

System.Windows.Forms.ListBindingHelper.GetListItemType() и GetListItemProperties()

Этот класс имеет все, что я искал.

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.

+0

Изучив это, метод GetItemProperties выглядит так, как будто это не поможет. Вы должны передать список свойств, а затем вернуть те, которые существуют в элементе. Поэтому это возвращает меня к вопросу о том, как получить тип элемента для получения списка свойств. Я отредактирую вопрос, чтобы удалить неправильную спекуляцию на эту точку. –

+0

@Preston: Посмотрите на редактирование. –

+0

Здесь достаточно думать, что я уверен, что не будет способа получить тип элемента непосредственно из BindingSource, как я надеялся. Я думаю, мне просто нужно ограничить область действия и предположить, что BindingSource будет иметь общий тип списка или тип, полученный из общего типа списка, заданного как DataSource, и просто перейти оттуда ... или связанный напрямую элемент , В любом случае вы получаете эту идею, снимаете границы дел и проблема исчезает. Спасибо за ваши мысли. –

1

Это было довольно долгое время, так как этот ответ был на борту, но только в случае, если кто-нибудь все еще ищет ответ ...

я столкнулся с подобной проблемой. Мой сценарий состоял в том, что 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; 

Не делая много исследований, я как бы предположить, что он делает это показывает тип элемента в InnerList, поэтому он оленья кожа Не имеет значения, является ли DataSource типом списка или нет. Кроме того, я предполагаю, что это поле будет точно показывать тип элемента любого вида списка, который поддерживается BindingSource (включая IQueryables и т. Д.).

ВНИМАНИЕ: Я НЕ тестировал это поле, поэтому не знаю, есть ли случаи, которые бы не отображали правильный тип элемента. Например, постоянно ли обновляется поле, когда свойство DataSource BindingSource перезагружается? Что делать, если свойство DataSource сбрасывается в список с другим типом elementType? В моем случае эти исключения и другие не применяются, но вы можете протестировать их.

Наконец, использование отражения для взлома в частных полях разрушает все виды принципов oop. Запомни. Кроме того, имейте в виду, что очень хорошо может быть хорошей причиной, почему поле itemType было скрыто. Если вам необходимо дополнительно исследовать, код для класса BindingSource доступен для общественности.

Смежные вопросы