Delphi Rtti Get 属性 - 为什么这会导致 AV?
Delphi Rtti Get Property - Why does this results in AV?
我正在尝试编写一个规范实用程序库。
规范之一是 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.
GetValue
需要实例指针 (aObject
) 但您将指针变量 (@aObject
) 的地址传递给它。
将您的 TObjectType
限制为 class 类型:
type
TPropertyExpression<TObjectType: class; TResultType> = class...
然后,直接传递实例而不是Addr(aObject)
:
aValue := aProperty.GetValue(Pointer(aObject));
我正在尝试编写一个规范实用程序库。
规范之一是 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.
GetValue
需要实例指针 (aObject
) 但您将指针变量 (@aObject
) 的地址传递给它。
将您的 TObjectType
限制为 class 类型:
type
TPropertyExpression<TObjectType: class; TResultType> = class...
然后,直接传递实例而不是Addr(aObject)
:
aValue := aProperty.GetValue(Pointer(aObject));