如何创建只读属性?

时间:2011-04-21 02:45:37

标签: delphi

我在运行时使用TMS对象检查器,但假设我的问题在设计时对Delphi同样有效。

我想拥有一个可以通过编程(在运行时)或硬编码(在设计时)设置的属性。它应该对用户可见,因为信息对他有用,它应该在程序运行时更改,但不能由用户通过对象检查器更改。

我试过

published property FileName : String read FFileName;

并且该属性是可见的,但它也可以在对象检查器中更改(并在更改时抛出读取地址zer0异常): - (

3 个答案:

答案 0 :(得分:9)

这看起来像一个完全有效且正确的只读属性

published property FileName : String read FFileName;

如果您添加一个公共的额外属性,因此只能在运行时运行时设置:

public property RuntimeFilename: string read FFileName write FFilename;
//note that two properties, one published and one public point to the same field.

但是如果你想破解它并在设计时除掉异常
将其更改为:

//Only writable during runtime.
private
  procedure SetFileName(Value: string);
published
  property FileName: string read FFileName write SetFileName;

....
procedure TMyClass.SetFileName(Value: string);
begin
  if csDesigning in Componentstate then {do nothing}
  else FFileName:= Value;
end;

我认为可能会发生什么......

断开设计时和运行时代码之间的连接
为了更改代码的运行时行为,您需要 更改源代码并删除属性的write ...部分。

但是会影响设计时代码,因为您需要重新安装组件。
如果您更改已注册组件的源代码,并且您在组件的privateprotected和/或public部分中保留更改,则通常可以。

但是,如果更改组件的published部分而未重新安装该组件,则启动时会出现异常行为。

这是因为在设计时中,您仍在使用组件的旧/未更改的二进制版本。此版本未删除write部分,并允许您更改基础字符串FFilename

运行时,init-code将读取表单资源1)并找到要写入FFilename的值。但是,过程SetFilename不再可用,因此在程序启动期间会发生访问冲突。

1)(.dfm文件中的数据,现在存储在.exe中的dfm资源中)

答案 1 :(得分:3)

最简单的方法:

private
  procedure SetFileName(Value: string);
published
  property FileName: string read FFileName write SetFileName;

....
procedure TMyClass.SetFileName(Value: string);
begin
  FFileName := FFileName;
end;

答案 2 :(得分:3)

这显然是TMS对象检查器中的错误,您应该使用TMS提交错误报告。