对象参数为 nil,无法确定原因
Object parameter is nil, can't determine why
我认为这应该非常简单,但我不知道为什么这不起作用。
我接管了遗留代码,并且 dll 中使用的一些对象变得难以管理。几个对象具有相同的过程
SetPropertyValue(propName,propValue:string);
现在,这些方法基本上是巨大的 if..else
语句,检查 propName
并分配 propValue
如果它匹配对象 属性:
if propName='name' then
name:=propValue
else if propName='address' then
address:=propValue
以此类推
每次对象获得一个新的 属性(或 属性 类型发生变化,因此传入的值参数需要进行不同的转换),此方法需要更新 - 显然是一件苦差事那不应该是。
我选择编写一个全局方法来设置一个对象 属性,它是动态的并且需要最少的维护。
这是我目前正在做的事情的一个简短例子。有两个单元,Obj 和 Main - 其中 Main 是一个带有 2 个编辑框和一个按钮的 VCL 表单,我使用按钮单击来触发 SetPropertyValue:
对象
unit Obj;
interface
uses
RTTI;
{$RTTI INHERIT}
type TmyObj = class(TObject)
Name:String;
Address:String;
City:String;
procedure SetPropertyValue(sPropName, sPropValue:String);
end;
procedure SetObjProperty(AObject : TObject; propName, propValue:String);
implementation
procedure SetObjProperty(AObject : TObject; propName, propValue:String);
var
context:TRttiContext;
rt: TRttiType;
prop: TRttiProperty;
begin
if not Assigned(AObject) then
exit;
context:=RTTIContext.Create;
rt:=Context.GetType(AObject.ClassType);
for prop in rt.GetProperties do
begin
//do some stuff
end;
Context.Free;
end;
{ TmyObj }
procedure TmyObj.SetPropertyValue(sPropName, sPropValue: String);
begin
SetObjProperty(self, sPropName, sPropValue);
end;
end.
主要
unit Main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
edtPropName: TEdit;
Label1: TLabel;
edtPropValue: TEdit;
btnGo: TButton;
procedure btnGoClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
Obj;
{$R *.dfm}
procedure TForm1.btnGoClick(Sender: TObject);
var
myObj:TMyObj;
begin
myObj:=TMyObj.Create;
myObj.SetPropertyValue(edtPropName.Text, edtPropValue.Text);
end;
end.
我没有更改 obj.SetPropertyValue
(因为我必须在代码中一遍又一遍地更改它),我只是引用了新过程。
不幸的是,无论我如何尝试引用 Obj.SetPropertyValyue
中的对象,它在 SetObjectProperty
中始终为空 - 因此 rt
始终为空并且循环不起作用任何东西。
我知道在传递一个对象时,我们只是在传递一个指针,所以即使我将参数类型更改为CONST
,当我输入新的时,我仍然得到相同的empty/nil值程序。
对我做错了什么有什么想法吗?我什至尝试在单元外引用 SetObjProperty
,所以:
thisObj:=TMyObj.Create;
SetObjProperty(thisObj,sThisName, sThisValue);
但在我的新方法中我仍然得到相同的 nil
obj。
我们将不胜感激!
Any thoughts on what I have down wrong?
您正在使用 RTTI, but your TMyObj
has no declared properties 循环属性。
这是一个小例子:
program Project62;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
RTTI;
{$RTTI INHERIT}
type
TmyObj = class(TObject)
private
FName:String;
FAddress:String;
FCity:String;
public
property Name: String read FName write FName;
property Address: String read FAddress write FAddress;
procedure SetPropertyValue(sPropName, sPropValue:String);
end;
procedure SetObjProperty(AObject : TObject; propName, propValue:String);
var
context:TRttiContext;
rt: TRttiType;
prop: TRttiProperty;
begin
if not Assigned(AObject) then begin
WriteLn('Not assigned');
exit;
end;
rt:= Context.GetType(AObject.ClassType);
for prop in rt.GetProperties do
begin
if (propName = 'Name') then
prop.SetValue(AObject,propValue)
else if (propName = 'Address') then
prop.SetValue(AObject,propValue);
end;
end;
procedure TmyObj.SetPropertyValue(sPropName, sPropValue: String);
begin
SetObjProperty(self, sPropName, sPropValue);
end;
var
myObj:TMyObj;
begin
myObj:= TMyObj.Create;
myObj.SetPropertyValue('Name', '1');
WriteLn(myObj.Name);
ReadLn;
end.
我认为这应该非常简单,但我不知道为什么这不起作用。
我接管了遗留代码,并且 dll 中使用的一些对象变得难以管理。几个对象具有相同的过程
SetPropertyValue(propName,propValue:string);
现在,这些方法基本上是巨大的 if..else
语句,检查 propName
并分配 propValue
如果它匹配对象 属性:
if propName='name' then
name:=propValue
else if propName='address' then
address:=propValue
以此类推
每次对象获得一个新的 属性(或 属性 类型发生变化,因此传入的值参数需要进行不同的转换),此方法需要更新 - 显然是一件苦差事那不应该是。
我选择编写一个全局方法来设置一个对象 属性,它是动态的并且需要最少的维护。
这是我目前正在做的事情的一个简短例子。有两个单元,Obj 和 Main - 其中 Main 是一个带有 2 个编辑框和一个按钮的 VCL 表单,我使用按钮单击来触发 SetPropertyValue:
对象
unit Obj;
interface
uses
RTTI;
{$RTTI INHERIT}
type TmyObj = class(TObject)
Name:String;
Address:String;
City:String;
procedure SetPropertyValue(sPropName, sPropValue:String);
end;
procedure SetObjProperty(AObject : TObject; propName, propValue:String);
implementation
procedure SetObjProperty(AObject : TObject; propName, propValue:String);
var
context:TRttiContext;
rt: TRttiType;
prop: TRttiProperty;
begin
if not Assigned(AObject) then
exit;
context:=RTTIContext.Create;
rt:=Context.GetType(AObject.ClassType);
for prop in rt.GetProperties do
begin
//do some stuff
end;
Context.Free;
end;
{ TmyObj }
procedure TmyObj.SetPropertyValue(sPropName, sPropValue: String);
begin
SetObjProperty(self, sPropName, sPropValue);
end;
end.
主要
unit Main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
edtPropName: TEdit;
Label1: TLabel;
edtPropValue: TEdit;
btnGo: TButton;
procedure btnGoClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
Obj;
{$R *.dfm}
procedure TForm1.btnGoClick(Sender: TObject);
var
myObj:TMyObj;
begin
myObj:=TMyObj.Create;
myObj.SetPropertyValue(edtPropName.Text, edtPropValue.Text);
end;
end.
我没有更改 obj.SetPropertyValue
(因为我必须在代码中一遍又一遍地更改它),我只是引用了新过程。
不幸的是,无论我如何尝试引用 Obj.SetPropertyValyue
中的对象,它在 SetObjectProperty
中始终为空 - 因此 rt
始终为空并且循环不起作用任何东西。
我知道在传递一个对象时,我们只是在传递一个指针,所以即使我将参数类型更改为CONST
,当我输入新的时,我仍然得到相同的empty/nil值程序。
对我做错了什么有什么想法吗?我什至尝试在单元外引用 SetObjProperty
,所以:
thisObj:=TMyObj.Create;
SetObjProperty(thisObj,sThisName, sThisValue);
但在我的新方法中我仍然得到相同的 nil
obj。
我们将不胜感激!
Any thoughts on what I have down wrong?
您正在使用 RTTI, but your TMyObj
has no declared properties 循环属性。
这是一个小例子:
program Project62;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
RTTI;
{$RTTI INHERIT}
type
TmyObj = class(TObject)
private
FName:String;
FAddress:String;
FCity:String;
public
property Name: String read FName write FName;
property Address: String read FAddress write FAddress;
procedure SetPropertyValue(sPropName, sPropValue:String);
end;
procedure SetObjProperty(AObject : TObject; propName, propValue:String);
var
context:TRttiContext;
rt: TRttiType;
prop: TRttiProperty;
begin
if not Assigned(AObject) then begin
WriteLn('Not assigned');
exit;
end;
rt:= Context.GetType(AObject.ClassType);
for prop in rt.GetProperties do
begin
if (propName = 'Name') then
prop.SetValue(AObject,propValue)
else if (propName = 'Address') then
prop.SetValue(AObject,propValue);
end;
end;
procedure TmyObj.SetPropertyValue(sPropName, sPropValue: String);
begin
SetObjProperty(self, sPropName, sPropValue);
end;
var
myObj:TMyObj;
begin
myObj:= TMyObj.Create;
myObj.SetPropertyValue('Name', '1');
WriteLn(myObj.Name);
ReadLn;
end.