有没有办法从通用约束类型获取 GUID?
Is there a way to get GUID from a generic constraint type?
在下面的示例代码中,Run<T>()
显示 GUID IFoo
和 IFoo<T>
接口的值:
type
IBar = interface
['{992E6597-42F1-40F8-B678-C4A86864B030}']
end;
IFoo = interface
['{0C589AF8-5727-4EAA-BB41-6D51D70B9D35}']
end;
IFoo<T> = interface(IFoo)
['{8FF54F6B-0896-4EA3-85F8-66BA70F9D2DA}']
end;
TTest = class
public
class procedure Run<T: IFoo>;
end;
class procedure TTest.Run<T>;
var
LContext: TRttiContext;
IFoo_T_TypeInfo: PTypeInfo;
IFooTypeInfo: PTypeInfo;
begin
IFoo_T_TypeInfo := TypeInfo(T);
IFooTypeInfo := LContext.GetType(TypeInfo(T)).BaseType.Handle;
WriteLn('IFoo<T> GUID: ', GetTypeData(IFoo_T_TypeInfo).GUID.ToString);
WriteLn('IFoo GUID: ', GetTypeData(IFooTypeInfo).GUID.ToString);
WriteLn('IBar GUID: ', '?');
end;
begin
TTest.Run<IFoo<IBar>>;
ReadLn;
end.
有没有办法从通用约束类型(在本例中为 IBar
接口)获取 TGUID
或 PTypeInfo
?
P.S.: 我不想将 Run<T>()
的签名更改为 Run<T, U>()
只是为了从 U.
获取 IBar
GUID
从泛型类型参数中获取 typeinfo/RTTI 有点棘手,但并非完全不可能。
下面是一些示例代码(我正在使用 Spring.Reflections 单元的 RTTI 扩展)。
uses
Rtti,
SysUtils,
Spring.Reflection;
type
TTest = class
public
class procedure Run<T: IFoo>;
end;
class procedure TTest.Run<T>;
var
LType, LType2: TRttiType;
begin
LType := TType.GetType(TypeInfo(T));
if LType.IsInterface then
begin
if LType.AsInterface.HasGuid then
Writeln(LType.Name, ' GUID: ', LType.AsInterface.GUID.ToString);
LType2 := LType.BaseType;
while Assigned(LType2) and (LType2.Handle <> TypeInfo(IInterface)) do
begin
if LType2.AsInterface.HasGuid then
Writeln(LType2.Name, ' GUID: ', LType2.AsInterface.GUID.ToString);
LType2 := LType2.BaseType;
end;
if LType.IsGenericType then
begin
for LType2 in LType.GetGenericArguments do
if Assigned(LType2) and LType2.IsInterface then
Writeln(LType2.Name, ' GUID: ', LType2.AsInterface.GUID.ToString);
end;
end
end;
var
bar: IBar;
begin
bar := TBar.Create; // cause RTTI for IBar to be generated to look it up later
TTest.Run<IFoo<IBar>>;
ReadLn;
end.
检查类型是否为泛型是通过类型名称的字符串解析完成的。如果它包含尖括号,则它是通用类型。然后它提取类型名称,这些名称始终是完全限定的类型名称,这使得查找它们成为可能。
然而,有一个问题需要牢记。只有当该类型的类型信息是在其他上下文中生成的,而不仅仅是泛型类型参数时,您才能查找这些信息。这就是为什么在该示例中我制作了一个实现 IBar 的简单 TBar class 并创建了一些实例以防止链接器剥离 class(和必要的 RTTI)。在实际代码中,这不是一个问题,因为您通常有该接口的一些实现。此外,为了使这个示例正常工作,您需要将接口放入它们自己的单元中,因为按完整限定名称查找不适用于 dpr 中的类型。
在下面的示例代码中,Run<T>()
显示 GUID IFoo
和 IFoo<T>
接口的值:
type
IBar = interface
['{992E6597-42F1-40F8-B678-C4A86864B030}']
end;
IFoo = interface
['{0C589AF8-5727-4EAA-BB41-6D51D70B9D35}']
end;
IFoo<T> = interface(IFoo)
['{8FF54F6B-0896-4EA3-85F8-66BA70F9D2DA}']
end;
TTest = class
public
class procedure Run<T: IFoo>;
end;
class procedure TTest.Run<T>;
var
LContext: TRttiContext;
IFoo_T_TypeInfo: PTypeInfo;
IFooTypeInfo: PTypeInfo;
begin
IFoo_T_TypeInfo := TypeInfo(T);
IFooTypeInfo := LContext.GetType(TypeInfo(T)).BaseType.Handle;
WriteLn('IFoo<T> GUID: ', GetTypeData(IFoo_T_TypeInfo).GUID.ToString);
WriteLn('IFoo GUID: ', GetTypeData(IFooTypeInfo).GUID.ToString);
WriteLn('IBar GUID: ', '?');
end;
begin
TTest.Run<IFoo<IBar>>;
ReadLn;
end.
有没有办法从通用约束类型(在本例中为 IBar
接口)获取 TGUID
或 PTypeInfo
?
P.S.: 我不想将 Run<T>()
的签名更改为 Run<T, U>()
只是为了从 U.
IBar
GUID
从泛型类型参数中获取 typeinfo/RTTI 有点棘手,但并非完全不可能。
下面是一些示例代码(我正在使用 Spring.Reflections 单元的 RTTI 扩展)。
uses
Rtti,
SysUtils,
Spring.Reflection;
type
TTest = class
public
class procedure Run<T: IFoo>;
end;
class procedure TTest.Run<T>;
var
LType, LType2: TRttiType;
begin
LType := TType.GetType(TypeInfo(T));
if LType.IsInterface then
begin
if LType.AsInterface.HasGuid then
Writeln(LType.Name, ' GUID: ', LType.AsInterface.GUID.ToString);
LType2 := LType.BaseType;
while Assigned(LType2) and (LType2.Handle <> TypeInfo(IInterface)) do
begin
if LType2.AsInterface.HasGuid then
Writeln(LType2.Name, ' GUID: ', LType2.AsInterface.GUID.ToString);
LType2 := LType2.BaseType;
end;
if LType.IsGenericType then
begin
for LType2 in LType.GetGenericArguments do
if Assigned(LType2) and LType2.IsInterface then
Writeln(LType2.Name, ' GUID: ', LType2.AsInterface.GUID.ToString);
end;
end
end;
var
bar: IBar;
begin
bar := TBar.Create; // cause RTTI for IBar to be generated to look it up later
TTest.Run<IFoo<IBar>>;
ReadLn;
end.
检查类型是否为泛型是通过类型名称的字符串解析完成的。如果它包含尖括号,则它是通用类型。然后它提取类型名称,这些名称始终是完全限定的类型名称,这使得查找它们成为可能。
然而,有一个问题需要牢记。只有当该类型的类型信息是在其他上下文中生成的,而不仅仅是泛型类型参数时,您才能查找这些信息。这就是为什么在该示例中我制作了一个实现 IBar 的简单 TBar class 并创建了一些实例以防止链接器剥离 class(和必要的 RTTI)。在实际代码中,这不是一个问题,因为您通常有该接口的一些实现。此外,为了使这个示例正常工作,您需要将接口放入它们自己的单元中,因为按完整限定名称查找不适用于 dpr 中的类型。