作为函数结果的属性具有空 属性 值?
Attribute as result of function has empty property value?
program Test;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Rtti;
function GetPropertyValue(const AObject: TObject; APropertyName: string): TValue;
var
oType: TRttiType;
oProp: TRttiProperty;
begin
oType := TRttiContext.Create.GetType(AObject.ClassType);
if oType <> nil then
begin
oProp := oType.GetProperty(APropertyName);
if oProp <> nil then
Exit(oProp.GetValue(AObject));
end;
Result := TValue.Empty;
end;
function GetAttributePropertyValue(const AClass: TClass; AAttribute: TClass;
AAttributePropertyName: string): TValue;
var
oAttr: TCustomAttribute;
begin
for oAttr in TRttiContext.Create.GetType(AClass).GetAttributes do
if oAttr.InheritsFrom(AAttribute) then
Exit(GetPropertyValue(oAttr, AAttributePropertyName));
Result := nil;
end;
function GetClassAttribute(const AClass: TClass; AAttribute: TClass): TCustomAttribute;
begin
for Result in TRttiContext.Create.GetType(AClass).GetAttributes do
if Result.InheritsFrom(AAttribute) then
Exit;
Result := nil;
end;
type
DescriptionAttribute = class(TCustomAttribute)
private
FDescription: string;
public
constructor Create(const ADescription: string);
property Description: string read FDescription;
end;
constructor DescriptionAttribute.Create(const ADescription: string);
begin
FDescription := ADescription;
end;
type
[Description('MyClass description')]
TMyClass = class(TObject);
var
oAttr: TCustomAttribute;
begin
{ ok, output is 'MyClass description' }
WriteLn(GetAttributePropertyValue(TMyClass, DescriptionAttribute, 'Description').AsString);
{ not ok, output is '' }
oAttr := GetClassAttribute(TMyClass, DescriptionAttribute);
WriteLn(DescriptionAttribute(oAttr).Description);
// WriteLn(oAttr.ClassName); // = 'DescriptionAttribute'
ReadLn;
end.
我需要 rtti 属性。我希望通过函数 GetClassAttribute()
获取属性,但结果不是预期的。
函数 GetAttributePropertyValue()
的结果是正确的(第一个 WriteLn),但函数 GetClassAttribute()
的结果是 DescriptionAttribute 的 Description 值为空。为什么?
获取属性作为函数结果的正确方法是什么?
TIA 和最诚挚的问候
布兰科
问题在于,如果 TRttiContext 超出范围,则在查询信息期间创建的所有 RTTI 相关对象(包括属性)都将被销毁。
当你在你的属性上放置一个析构函数时,你可以验证这一点 class。
最新版本在 TRttiContext
上引入了 KeepContext
和 DropContext
方法,您可以使用或只是将全局变量放在某处并通过调用 [=13= 触发内部创建] 或者其他的东西。我通常使用 RTTI 将 TRttiContext
变量作为 class 变量放入 classes 中。
KeepContext
和 DropContext
可用于您可能没有一个全局 TRttiContext
实例来确保其生命周期的代码,因为您正在使用其他 classes,有自己的 TRttiContext
引用的方法和例程 - 例如,参见它在 System.Classes
中的使用,其中在 BeginGlobalLoading
期间调用 KeepContext
以及在 EndGlobalLoading
[=11 中=].
program Test;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Rtti;
function GetPropertyValue(const AObject: TObject; APropertyName: string): TValue;
var
oType: TRttiType;
oProp: TRttiProperty;
begin
oType := TRttiContext.Create.GetType(AObject.ClassType);
if oType <> nil then
begin
oProp := oType.GetProperty(APropertyName);
if oProp <> nil then
Exit(oProp.GetValue(AObject));
end;
Result := TValue.Empty;
end;
function GetAttributePropertyValue(const AClass: TClass; AAttribute: TClass;
AAttributePropertyName: string): TValue;
var
oAttr: TCustomAttribute;
begin
for oAttr in TRttiContext.Create.GetType(AClass).GetAttributes do
if oAttr.InheritsFrom(AAttribute) then
Exit(GetPropertyValue(oAttr, AAttributePropertyName));
Result := nil;
end;
function GetClassAttribute(const AClass: TClass; AAttribute: TClass): TCustomAttribute;
begin
for Result in TRttiContext.Create.GetType(AClass).GetAttributes do
if Result.InheritsFrom(AAttribute) then
Exit;
Result := nil;
end;
type
DescriptionAttribute = class(TCustomAttribute)
private
FDescription: string;
public
constructor Create(const ADescription: string);
property Description: string read FDescription;
end;
constructor DescriptionAttribute.Create(const ADescription: string);
begin
FDescription := ADescription;
end;
type
[Description('MyClass description')]
TMyClass = class(TObject);
var
oAttr: TCustomAttribute;
begin
{ ok, output is 'MyClass description' }
WriteLn(GetAttributePropertyValue(TMyClass, DescriptionAttribute, 'Description').AsString);
{ not ok, output is '' }
oAttr := GetClassAttribute(TMyClass, DescriptionAttribute);
WriteLn(DescriptionAttribute(oAttr).Description);
// WriteLn(oAttr.ClassName); // = 'DescriptionAttribute'
ReadLn;
end.
我需要 rtti 属性。我希望通过函数 GetClassAttribute()
获取属性,但结果不是预期的。
函数 GetAttributePropertyValue()
的结果是正确的(第一个 WriteLn),但函数 GetClassAttribute()
的结果是 DescriptionAttribute 的 Description 值为空。为什么?
获取属性作为函数结果的正确方法是什么?
TIA 和最诚挚的问候 布兰科
问题在于,如果 TRttiContext 超出范围,则在查询信息期间创建的所有 RTTI 相关对象(包括属性)都将被销毁。
当你在你的属性上放置一个析构函数时,你可以验证这一点 class。
最新版本在 TRttiContext
上引入了 KeepContext
和 DropContext
方法,您可以使用或只是将全局变量放在某处并通过调用 [=13= 触发内部创建] 或者其他的东西。我通常使用 RTTI 将 TRttiContext
变量作为 class 变量放入 classes 中。
KeepContext
和 DropContext
可用于您可能没有一个全局 TRttiContext
实例来确保其生命周期的代码,因为您正在使用其他 classes,有自己的 TRttiContext
引用的方法和例程 - 例如,参见它在 System.Classes
中的使用,其中在 BeginGlobalLoading
期间调用 KeepContext
以及在 EndGlobalLoading
[=11 中=].