Как через механизмы рефелексии получить доступ к типу, хранящемуся в List<T>?
public struct Info
{
[Attribute1(100),
Attribute2("aaa")]
public PropertyA { get; set; }
[Attribute1(150),
Attribute2("bbb")]
public PropertyB { get; set; }
}
// где-то дальше в коде (про структуру Info здесь ничего неизвестно)
// известно лишь, что DataSource реально представляет из себя список List<T>
// и известны имена свойств "PropertyA" и "PropertyB"
// и здесь нужно добраться до атрибутов этих свойств
//
DataSource ...
03.12.09 08:54: Перенесено модератором из '.NET' — TK
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Андрей, Вы писали:
А>>Всем доброго времени суток!
А>>Как через механизмы рефелексии получить доступ к типу, хранящемуся в List<T>?
S>typeof(mylist).GetGenericArguments()
это, конечно, сработало
но дело в том, что мне приходит List<object>, а реально в этом листе сидят структуры, подобные вышеописанным
и естественно, что GetGenericArguments() возвращает мне object
как откастить этот object к реальному типу и получить свойства?
Здравствуйте, Андрей, Вы писали:
А>это, конечно, сработало
А>но дело в том, что мне приходит List<object>, а реально в этом листе сидят структуры, подобные вышеописанным А>и естественно, что GetGenericArguments() возвращает мне object
А>как откастить этот object к реальному типу и получить свойства?
Тогда object — и есть реальный тип элементов списка
Может пересоздать список, приведя каждый элемент к нужному типу?
Здравствуйте, Андрей, Вы писали:
А>Здравствуйте, samius, Вы писали:
S>>Здравствуйте, Андрей, Вы писали:
S>>typeof(mylist).GetGenericArguments()
А>это, конечно, сработало
А>но дело в том, что мне приходит List<object>, а реально в этом листе сидят структуры, подобные вышеописанным А>и естественно, что GetGenericArguments() возвращает мне object
А>как откастить этот object к реальному типу и получить свойства?
Подобные вышеописанным, или в точности вышеописанные?
Если в точности, то можно воспользоваться оператором приведения типа без рефлексии. Если подобные — у каждого элемента вызывать метод GetType() и дальше по обстоятельствам.
Здравствуйте, Пельмешко, Вы писали:
П>Здравствуйте, Андрей, Вы писали:
А>>это, конечно, сработало
А>>но дело в том, что мне приходит List<object>, а реально в этом листе сидят структуры, подобные вышеописанным А>>и естественно, что GetGenericArguments() возвращает мне object
А>>как откастить этот object к реальному типу и получить свойства?
П>Тогда object — и есть реальный тип элементов списка П>Может пересоздать список, приведя каждый элемент к нужному типу? П>
П>myNeList = myList.Cast<Info>().ToList();
П>
хм, таких структур не одна, к сожалению
поэтому пересоздать список в данном случае невозможно
списки я получаю через методы интерфейса, а они возвращают List<object>
и там, где я их получаю, мне реально сидящий тип не особо и нужен
мне нужно только получить у свойств (а их имена известны) атрибуты с тоже известными именами
интересно, а как DataGridView работает в данном случае?
он вполне нормально достает из моих списков List<object> нужные ему атрибуты (в частности, DisplayNameAttribute для каждого поля структуры)
Здравствуйте, Андрей, Вы писали:
А>списки я получаю через методы интерфейса, а они возвращают List<object> А>и там, где я их получаю, мне реально сидящий тип не особо и нужен А>мне нужно только получить у свойств (а их имена известны) атрибуты с тоже известными именами
А>интересно, а как DataGridView работает в данном случае? А>он вполне нормально достает из моих списков List<object> нужные ему атрибуты (в частности, DisplayNameAttribute для каждого поля структуры)
Через всякие TypeDescriptor'ы оно работает, а оные через рефлексию...
И Вам тоже так придётся, как написали выше, .GetType() у каждого элемента, потом .GetProperties(), .GetCustomAttributes() и в бой...
skip
П>Через всякие TypeDescriptor'ы оно работает, а оные через рефлексию...
а можно поподробнее с этого места?
П>И Вам тоже так придётся, как написали выше, .GetType() у каждого элемента, потом .GetProperties(), .GetCustomAttributes() и в бой...
не выходит каменный цветок с List<object> — мне возвращается System.Object и все, дальше оно не идет
само собой, что у этого object нет ни свойств, ни атрибутов
skip
S>Подобные вышеописанным, или в точности вышеописанные?
S>Если в точности, то можно воспользоваться оператором приведения типа без рефлексии. Если подобные — у каждого элемента вызывать метод GetType() и дальше по обстоятельствам.
оператор приведения типа мне не подходит — я не знаю в этом месте реальных типов
а про GetType для каждого элемента — непонятно
List<Object>.GetGenericArguments() возвращает массив из одного элемента typeof(object).
что с ним дальше делать — абсолютно не представляю, получать от него новый Type — бесполезно, пытаться получить Properties или создать TypeDescriptor — тоже
Здравствуйте, Андрей, Вы писали:
П>>И Вам тоже так придётся, как написали выше, .GetType() у каждого элемента, потом .GetProperties(), .GetCustomAttributes() и в бой...
А>не выходит каменный цветок с List<object> — мне возвращается System.Object и все, дальше оно не идет А>само собой, что у этого object нет ни свойств, ни атрибутов
По-моему всё что Вам нужно — рефлексия, вот кривой пример как прочитать все свойства, отмеченные [ObsoleteAttribute]:
class Foo
{
[Obsolete]
public int Value { get; set; }
}
class Bar
{
[Obsolete]
public string Hello { get; set; }
}
class Program
{
private static void Main()
{
var list = new List<object> {
new Foo { Value = 45 },
new Bar { Hello = "hello!" }
};
foreach (object obj in list)
{
var marketProperties = obj
.GetType()
.GetProperties()
.Where(prop =>
Attribute.IsDefined(prop, typeof(ObsoleteAttribute)));
foreach(var prop in marketProperties)
{
Console.WriteLine(prop.GetValue(obj, null));
}
}
}
}
Вполне возможно, что это проще решается через TypeDescriptor, но я не разбирался с ним совсем...
Здравствуйте, Андрей, Вы писали:
А>Здравствуйте, samius, Вы писали:
А>skip
S>>Подобные вышеописанным, или в точности вышеописанные?
S>>Если в точности, то можно воспользоваться оператором приведения типа без рефлексии. Если подобные — у каждого элемента вызывать метод GetType() и дальше по обстоятельствам.
А>оператор приведения типа мне не подходит — я не знаю в этом месте реальных типов А>а про GetType для каждого элемента — непонятно
но вот какая засада: а если в коллекции нет элементов?
то есть что-то типа:
class Foo
{
[Obsolete]
public int Value {get;set;}
}
class Program
{
private static void Main()
{
var list = new List<Foo>();
// здесь я этот list куда-то передаю
// там, где его принимают, про тип Foo не имеют понятия
// все, что о нем известно - что у него есть свойство с именем Value и у этого свойства возможно есть атрибут Obsolete
}
}
меня как раз этот случай и интересует — когда на вход подается пустая коллекция
чтобы было понятней: я пытаюсь настроить ширину полей (а также некоторые другие аспекты внешнего вида) DataGridView через атрибуты полей коллекции привязанной к DataSource
типов этих коллекций может быть довольно много (то есть List<Structure1>, List<Structure2> и т.д.), и я не знаю, с какой структурой я работаю в данный момент
если эта структура имеет элементы — никаких проблем не возникает
через первый элемент коллекции я получаю нужные мне атрибуты
проблема возникает, когда на вход приходит пустая коллекция — в этом случае я никак не могу узнать типы полей, так как нет текущего элемента
Здравствуйте, Андрей, Вы писали:
А>Здравствуйте, Пельмешко, Вы писали:
А>skip
А>ок, я понял
А>но вот какая засада: а если в коллекции нет элементов?
А>меня как раз этот случай и интересует — когда на вход подается пустая коллекция
А>чтобы было понятней: я пытаюсь настроить ширину полей (а также некоторые другие аспекты внешнего вида) DataGridView через атрибуты полей коллекции привязанной к DataSource А>типов этих коллекций может быть довольно много (то есть List<Structure1>, List<Structure2> и т.д.), и я не знаю, с какой структурой я работаю в данный момент
А>если эта структура имеет элементы — никаких проблем не возникает А>через первый элемент коллекции я получаю нужные мне атрибуты
А>проблема возникает, когда на вход приходит пустая коллекция — в этом случае я никак не могу узнать типы полей, так как нет текущего элемента
Тогда возвращаемся к началу, делаете раз:
var type = grid.DataSource.GetType();
А потом исследуете тип, которым параметризован List<T>:
// сразу предупреждаю, не будет работать с наследниками List<>if (type.IsGenericType &&
type.GetGenericDefinition() == typeof(List<>))
{
var elementType = type.GetGenericArguments()[0];
elementType.GetProperties() ....
}
Вообще, наверное, надо не на List<T> проверять, а ниже, вроде биндить можно ко всему, начиная с IEnumerable<T>...
Здравствуйте, Пельмешко, Вы писали:
П>Вообще, наверное, надо не на List<T> проверять, а ниже, вроде биндить можно ко всему, начиная с IEnumerable<T>...
вообще интересная ситуация получается: если я в DataGridView в качестве DataSource задаю object (а на самом деле List<myStructure>), то все получается как надо: рефлексия работает на ура
а вот если List<object> (где на самом деле вместо object находятся экземпляры myStructure), то все встает раком
при этом сам DataGridView без проблем съедает все варианты
раскопать бы код в DataGridView, который разбирает атрибуты полей
Здравствуйте, Андрей, Вы писали:
А>Здравствуйте, samius, Вы писали:
А>skip
А>обоим поставил — мне не жалко за здравые идеи
А>вообще интересная ситуация получается: если я в DataGridView в качестве DataSource задаю object (а на самом деле List<myStructure>), то все получается как надо: рефлексия работает на ура А>а вот если List<object> (где на самом деле вместо object находятся экземпляры myStructure), то все встает раком
А>при этом сам DataGridView без проблем съедает все варианты
Наверное потому что оно получает List<object> с элементами, и исследует их... Без элементов в List<object> DataGrid не сможет ничего исследовать...
Вы можете скомбинировать оба варианта: когда type == typeof(List<object>) заглядывать внутрь листа и поглядеть какого типа элементы...
Здравствуйте, Андрей, Вы писали:
А>Всем доброго времени суток!
А>Как через механизмы рефелексии получить доступ к типу, хранящемуся в List<T>?
А>
А>public struct Info
А>{
А> [Attribute1(100),
А> Attribute2("aaa")]
А> public PropertyA { get; set; }
А> [Attribute1(150),
А> Attribute2("bbb")]
А> public PropertyB { get; set; }
А>}
А>// где-то дальше в коде (про структуру Info здесь ничего неизвестно)
А>// известно лишь, что DataSource реально представляет из себя список List<T>
А>// и известны имена свойств "PropertyA" и "PropertyB"
А>// и здесь нужно добраться до атрибутов этих свойств
А>//
А>DataSource ...
А>
Попробуйте ListBindingHelper, если вас не пугает перспектива подключения сборки System.Windows.Forms.
Через него собственно все контролы и работают.
skip
sto>Попробуйте ListBindingHelper, если вас не пугает перспектива подключения сборки System.Windows.Forms. sto>Через него собственно все контролы и работают.