在我的应用程序中,我定义了许多集合:
eBlockTypes = (btNone,btUndefined,btStone, btYellowFlower, btWoodBrown...);
sMinerals = set of eBlockTypes;
var
mineralsRare: sMinerals;
mineralsPlants: sMinerals;
mineralsAll: sMinerals;
mineralsDeep: sMinerals;
mineralsWalkable: sMinerals;
mineralsDiggable: sMinerals;
然后我有一个将'sMinerals'作为其中一个字段的对象。从文件加载对象属性时是否可以读取set的'name'?
编辑:更多细节。假设文件中的对象定义如下:
[item]
Computer
[requires]
3 Circuit board
1 Medium CPU
3 Plastic
[placement]
mineralsWalkable
所以我可以解析文件并读取除了'mineralsWalkable'之外的所有属性。 我知道我可以将该字符串与一些保存所有集合名称的TStrings进行比较,但静止是:是否可以通过将字符串转换为变量来获取该字符串?
答案 0 :(得分:1)
您可以从文件中读取的内容取决于文件中的内容。如果您将变量的名称写入文件,那么您也应该能够阅读它们。如果没有,那么你不能。但是,当您编写数据时,变量名称本身并不会写入文件。
确定用于将名称写入文件的技术。要阅读它们,只需执行反向操作即可。如果您以某种方式编写了分隔的数据,则读取直到遇到分隔符。如果您在名称前面加上字符长度,则读取长度,然后读取那么多字符。如果你没有使用可逆的技术编写名称,那么在继续阅读之前你必须改变你编写数据的方式。
你的问题是否可以阅读这些名字,答案是肯定的。您之后提出了另一个问题,即是否可以将从文件中读取的名称“转换”为具有相应名称的实际变量。答案是否定的。
普通变量没有RTTI; Delphi不维护程序中所有变量的名称。一旦编译器完成其工作,名称就不再存在于程序中。
获取变量的最简单方法是设置从字符串到设置值的映射。从文件中读取名称,在数据结构中查找名称,并使用相应的值。 TDictionary<string, sMinerals>
对此非常适合。只需在程序启动时填充数据结构即可。
答案 1 :(得分:0)
非常简单...... 您需要将变量mineralwalkable保存为eBlockTypes的字符串表示形式。您将使用GetEnumName来执行此操作。 然后,您需要将eBlockTypes的字符串表示形式转换为实际的eBlockType,然后将其添加到mineralWalkable中。你将使用GetEnumValue来做到这一点。
以下示例显示了获取字符串表示形式...将其放置在一个集合中...然后将该集合...并将其移回字符串...
object Form54: TForm54
Left = 0
Top = 0
Caption = 'Form54'
ClientHeight = 290
ClientWidth = 554
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 56
Top = 160
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Edit1: TEdit
Left = 56
Top = 64
Width = 265
Height = 21
TabOrder = 1
Text = 'Edit1'
end
object cbType1: TCheckBox
Left = 248
Top = 91
Width = 97
Height = 17
Caption = 'Type1'
TabOrder = 2
end
object cbType2: TCheckBox
Tag = 1
Left = 248
Top = 114
Width = 97
Height = 17
Caption = 'Type2'
TabOrder = 3
end
object cbType3: TCheckBox
Tag = 2
Left = 248
Top = 137
Width = 97
Height = 17
Caption = 'Type3'
TabOrder = 4
end
end
unit Unit54;
{Note the code assumes cbType1.Tag = 0, cbType2.Tag = 1, and cbType3.Tag = 2}
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, TypInfo, IniFiles;
type
TMyType = (mtOne, mtTwo, mtThree);
TMyTypes= set of TMyType;
TForm54 = class(TForm)
Button1: TButton;
Edit1: TEdit;
cbType1: TCheckBox;
cbType2: TCheckBox;
cbType3: TCheckBox;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
function getTypes1: TMyTypes;
procedure setMyTypes1(const Value: TMyTypes);
{ Private declarations }
public
{ Public declarations }
property Types1: TMyTypes read getTypes1 write setMyTypes1;
procedure SaveMyTypes(aVariableName: string; aMyTypes: TMyTypes);
function ReadMyTypes(aVariableName: string): TMyTypes;
end;
var
Form54: TForm54;
implementation
{$R *.dfm}
procedure TForm54.Button1Click(Sender: TObject);
var
a_MyTypes: TMyTypes;
a_Str: string;
a_Index: integer;
begin
a_MyTypes := [];
a_Str := '';
Include(a_MyTypes, TMyType(GetEnumValue(TypeInfo(TMyType), 'mtOne')));
Include(a_MyTypes, TMyType(GetEnumValue(TypeInfo(TMyType), 'mtTwo')));
//purpoesly have mtThree3 instead of mtThree
Include(a_MyTypes, TMyType(GetEnumValue(TypeInfo(TMyType), 'mtThree3')));
for a_Index := Ord(Low(TMyType)) to Ord(High(TMyType)) do
if TMyType(a_Index) in a_MyTypes then
if a_Str = '' then
a_Str := GetEnumName(TypeInfo(TMyType), a_Index)
else
a_Str := a_Str + ',' + GetEnumName(TypeInfo(TMyType), a_Index);
//should be mtOne, mtTwo
Edit1.Text := a_Str;
end;
procedure TForm54.FormCreate(Sender: TObject);
begin
Types1 := ReadMyTypes('Types1');
end;
procedure TForm54.FormDestroy(Sender: TObject);
begin
SaveMyTypes('Types1', Types1);
end;
function TForm54.getTypes1: TMyTypes;
var
a_Index: integer;
begin
Result := [];
for a_Index := 0 to Self.ComponentCount - 1 do
if Self.Components[a_Index] is TCheckBox and (TCheckBox(Self.Components[a_Index]).Checked) then
Include(Result, TMyType(Self.Components[a_Index].Tag));
end;
function TForm54.ReadMyTypes(aVariableName: string): TMyTypes;
var
a_Ini: TIniFile;
a_Var: string;
a_List: TStrings;
a_Index: integer;
begin
Result := [];
a_Ini := nil;
a_List := nil;
a_Ini := TIniFile.Create('MyType.ini');
a_List := TStringList.Create;
try
a_Var := a_Ini.ReadString('Sets', aVariableName, '');
a_List.Delimiter := ',';
a_List.DelimitedText := a_Var;
for a_Index := 0 to a_List.Count - 1 do
begin
Include(Result, TMyType(GetEnumValue(TypeInfo(TMyType), a_List[a_Index])));
end;
finally
a_Ini.Free;
a_List.Free;
end;
end;
procedure TForm54.SaveMyTypes(aVariableName: string; aMyTypes: TMyTypes);
var
a_Ini: TIniFile;
a_Index: integer;
a_Var: string;
begin
a_Var := '';
a_Ini := TIniFile.Create('MyType.ini');
try
for a_Index := Ord(Low(TMyType)) to Ord(High(TMyType)) do
if TMyType(a_Index) in aMyTypes then
if a_Var = '' then
a_Var := GetEnumName(TypeInfo(TMyType), a_Index)
else
a_Var := a_Var + ',' + GetEnumName(TypeInfo(TMyType), a_Index);
a_Ini.WriteString('Sets', aVariablename, a_Var);
finally
a_Ini.Free;
end;
end;
procedure TForm54.setMyTypes1(const Value: TMyTypes);
var
a_Index: integer;
begin
for a_Index := 0 to Self.ComponentCount - 1 do
if Self.Components[a_Index] is TCheckBox then
TCheckBox(Self.Components[a_Index]).Checked := TMyType(TCheckBox(Self.Components[a_Index]).Tag) in Value;
end;
end.