【问题标题】:Delphi Rtti Get Property - Why does this results in AV?Delphi Rtti Get Property - 为什么这会导致 AV?
【发布时间】:2016-04-23 03:05:51
【问题描述】:

我正在尝试编写一个规范实用程序库。

规范之一是 TExpressionSpecification。基本上,它通过评估内部 TExpression 来实现规范模式。

TExpression 之一是 TPropertyExpression。它只是一个表达式,它通过 Rtti 的名称获取属性的值。

我以最简单的方式实现了它,但真的不明白为什么它会向我抛出 AV。

我对调试器进行了深入研究。所有类型都是它们应该是的。我只是不知道为什么 TRttiProperty.GetValue 会造成严重破坏。

有人可以帮忙吗? 单位规格;

interface

uses

Classes;

type

TPropertyExpression<TObjectType, TResultType> = class

private
  FPropertyName: string;
public
  constructor Create(aPropertyName: string); reintroduce;
  function Evaluate(aObject: TObjectType): TResultType;
  property PropertyName: string read FPropertyName write FPropertyName;
end;

procedure TestIt;

implementation

uses

Rtti;

constructor TPropertyExpression<TObjectType, TResultType>.Create(aPropertyName:
    string);
begin
  inherited Create;
  PropertyName := aPropertyName;
end;

function TPropertyExpression<TObjectType, TResultType>.Evaluate(aObject:
    TObjectType): TResultType;
var
  aCtx : TRttiContext;
  aModelType : TRttiType;
  aResultType : TRttiType;
  aProperty : TRttiProperty;
  aValue : TValue;
begin
  aCtx := TRttiContext.Create;
  aModelType := aCtx.GetType(System.TypeInfo(TObjectType));
  aResultType := aCtx.GetType(System.TypeInfo(TResultType));
  aProperty := aModelType.GetProperty(PropertyName);
  aValue := aProperty.GetValue(Addr(aObject));
  Result := aValue.AsType<TResultType>;  
end;

procedure TestIt;
var
  aComponent : TComponent;
  aSpec : TPropertyExpression<TComponent, string>;
begin
  aComponent := TComponent.Create(nil);
  aComponent.Name := 'ABC';
  aSpec := TPropertyExpression<TComponent, string>.Create('Name');
  WriteLn(aSpec.Evaluate(aComponent));
  Readln; 
end;

end.

【问题讨论】:

    标签: delphi generics rtti


    【解决方案1】:

    GetValue 需要实例指针 (aObject),但您将指针变量的地址 (@aObject) 传递给它。

    将您的 TObjectType 限制为类类型:

    type
      TPropertyExpression<TObjectType: class; TResultType> = class...
    

    然后,直接传递实例,而不是Addr(aObject)

      aValue := aProperty.GetValue(Pointer(aObject));
    

    【讨论】:

    • 无需类型转换为Pointer,只需按原样传递对象指针:GetValue(aObject)
    • 另外,请记住记录也可以具有属性,因此您不应使用class 约束。除非您定义一个单独的表达式类来分别处理记录实例和类实例。
    • 没有演员表,我得到 E2010 不兼容的类型:“指针”和“TObjectType”。虽然您是对的,记录可以具有属性,但不支持记录属性的 RTTI。所以我只是假设只限制类类型是可以的。
    • 我最近在 rtti 上回答了一个关于记录属性的问题。我认为这是支持的。
    • @DavidHeffernan 从我对上面代码的实验中,aModelType.GetProperty 对于记录类型总是返回 nil。此外,documentation 表示不支持(也许我误解了它)。
    猜你喜欢
    • 2013-02-25
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 2017-04-26
    • 1970-01-01
    • 2012-05-04
    相关资源
    最近更新 更多