Delphi 作为函数结果的属性是否具有空属性值?

Delphi 作为函数结果的属性是否具有空属性值?,delphi,attributes,rtti,Delphi,Attributes,Rtti,我需要rtti属性。我希望通过函数GetClassAttribute获得属性,但结果不是预期的 函数GetAttributePropertyValue的结果在第一次写入时是正确的,但函数GetClassAttribute的结果是DescriptionAttribute,其描述值为空。为什么? 获取属性作为函数结果的正确方法是什么 祝你一切顺利 Branko问题在于,如果TRttiContext超出范围,则在查询信息(包括属性)期间创建的所有RTTI相关对象都将被销毁 在属性类上放置析构函数时,可

我需要rtti属性。我希望通过函数GetClassAttribute获得属性,但结果不是预期的

函数GetAttributePropertyValue的结果在第一次写入时是正确的,但函数GetClassAttribute的结果是DescriptionAttribute,其描述值为空。为什么?

获取属性作为函数结果的正确方法是什么

祝你一切顺利
Branko

问题在于,如果TRttiContext超出范围,则在查询信息(包括属性)期间创建的所有RTTI相关对象都将被销毁

在属性类上放置析构函数时,可以验证这一点

最近的版本在TRttiContext上引入了KeepContext和DropContext方法,您可以使用或只是将一个全局变量放在某个地方,并通过调用Create或其他方法使其触发内部创建。我通常使用RTTI将TRttiContext变量作为类变量放入类中


KeepContext和DropContext可以在代码中使用,因为您使用的是其他类,所以可能没有一个全局TrtContext实例可以确保其生存期,具有自己的TRttiContext引用的方法和例程-例如,请参见其在System.Class中的使用,其中在BeginGlobalLoading期间调用KeepContext,在EndGlobalLoading DropContext中使用。

对不起,我不理解KeepContext和DropContext的用法。请解释如何在我的情况下使用这个。谢谢更新的答案。对不起,我不能投两次票;
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.