In Delphi, if I have a TValue
instance reflecting an unknown object, how can I test if this object is an instance of ANY kind of generic TEnumerable<>
(or even better, also which specific generic enumerable type it is an instance of, e.g. TList<>
)?
NOTE: I already know how to easily check its exact type, i.e. with the .BaseType
property of the corresponding TRttiType
of the TValue
, resulting in for example TList<string>
, but what I want to test is rather if it is a TList<>
of any sub-item type.
To exemplify how this hypothetical code "IsAnyKindOfGenericEnumerable()" would work, here is some example code:
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
And again, the very best thing would be if I could also detect which kind of TEnumerable<>
type it is, like for example:
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<>`
I have tried:
if obj_1_rtti_type is TRttiEnumerationType then
begin
//...
end;
but for some reason this evaluates to false
, which I'm completely at loss as to why that is? The expression value_type.BaseType.Name
does indeed evaluate to 'TEnumerable<System.string>'
in this case, but there really has to be some other way than to manually parse this string in order to accomplish my objective, right?
Finally, the goal must be accomplished solely using the RTTI info, that is, any "cheating" by referring to the real object behind the TValue is not permitted (for reasons outside the scope of this question).