Ich versuche, eine Spezifikation Dienstprogrammbibliothek zu schreiben.Delphi Rtiti Get Property - Warum ergibt dies AV?
Eine der Spezifikationen ist eine TExpressionSpecification. Im Grunde wird das Spezifikationsmuster implementiert, indem eine innere TExpression ausgewertet wird.
Einer der TExpression ist ein TPropertyExpression. Es ist einfach ein Ausdruck, der den Wert einer Eigenschaft durch ihren Namen mit Rtti bekommt.
Ich implementierte es auf die einfachste Weise, die ich könnte, aber kann wirklich nicht verstehen, warum es ein AV auf mich wirft.
Ich trat mit dem Debugger Thoroughly. Alle Arten sind, was sie sein sollen. Ich weiß nicht, warum der TRttiProperty.GetValue verheerend ist.
Kann jemand helfen? Einheit Spec;
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.
Es gibt keine Notwendigkeit, 'Pointer' goss Typen, nur passieren der Objektzeiger wie-ist: 'GetValue (aObject)'. –
Denken Sie auch daran, dass Datensätze auch Eigenschaften haben können, also sollten Sie keine 'class' Einschränkung verwenden. Es sei denn, Sie definieren eine separate Ausdrucksklasse, um Datensatzinstanzen getrennt von Klasseninstanzen zu behandeln. –
Ohne die Besetzung, bekomme ich E2010 Inkompatible Typen: 'Zeiger' und 'TObjectType'. Und während Sie Recht haben, dass Datensätze Eigenschaften haben können, wird RTTI für Datensatzeigenschaften nicht unterstützt. Also habe ich einfach angenommen, dass es in Ordnung ist, nur auf Klassen zu beschränken. –