В Delphi, если у меня есть экземпляр TValue
, отражающий неизвестный объект, как я могу проверить, является ли этот объект экземпляром ЛЮБОГО типа универсального TEnumerable<>
(или, что еще лучше, также какого конкретного универсального перечисляемого типа) экземпляр, например TList<>
)?
ПРИМЕЧАНИЕ: я уже знаю, как легко проверить его точный тип, т. е. с помощью свойства .BaseType
соответствующего TRttiType
из TValue
, в результате чего, например, будет TList<string>
, но я хочу проверить скорее если это TList<>
подэлемента любого типа.
Чтобы проиллюстрировать, как этот гипотетический код "IsAnyKindOfGenericEnumerable()" будет работать, вот пример кода:
var
LContext : TRttiContext;
obj_1_rtti_value : TValue;
obj_2_rtti_value : TValue;
obj_3_rtti_value : TValue;
obj_1_rtti_type : TRttiType;
obj_2_rtti_type : TRttiType;
obj_3_rtti_type : TRttiType;
LContext := TRttiContext.Create();
{
...
obj_1_rtti_value is set to a TValue reflection of a TList<string> object here
obj_2_rtti_value is set to a TValue reflection of a plain TObject object here
obj_3_rtti_value is set to a TValue reflection of a TQueue<integer> object here
...
}
obj_1_rtti_type := LContext.GetType(obj_1_rtti_value.TypeInfo);
obj_2_rtti_type := LContext.GetType(obj_2_rtti_value.TypeInfo);
obj_3_rtti_type := LContext.GetType(obj_3_rtti_value.TypeInfo);
IsAnyKindOfGenericEnumerable(obj_1_rtti_type); //Would return true
IsAnyKindOfGenericEnumerable(obj_2_rtti_type); //Would return false
IsAnyKindOfGenericEnumerable(obj_3_rtti_type); //Would return true
И опять же, было бы лучше всего, если бы я мог определить какой тип TEnumerable<>
, например:
IsAnyKindOfGenericEnumerable(obj_1_rtti_type); //Will return true + `TList<>`
IsAnyKindOfGenericEnumerable(obj_2_rtti_type); //Will return false
IsAnyKindOfGenericEnumerable(obj_3_rtti_type); //Will return true + `TQueue<>`
Я пытался:
if obj_1_rtti_type is TRttiEnumerationType then
begin
//...
end;
но по какой-то причине это оценивается как false
, и я совершенно не понимаю, почему это так? Выражение value_type.BaseType.Name
действительно оценивается как 'TEnumerable<System.string>'
в этом случае, но действительно должен быть какой-то другой способ, кроме ручного разбора этой строки, для достижения моей цели, верно?
Наконец, цель должна быть достигнута исключительно с использованием информации RTTI, то есть любой «обман» путем обращения к реальному объекту за TValue не допускается (по причинам, выходящим за рамки этого вопроса).