接受任何类型的参数(例如:布尔值、字符串、浮点数等)

An argument that accepts any kind of Types (like: boolean, string, float.. etc)

我这里有这个代码:

type  // This Enumerator Type for Handling the Registry Results ...
 TRegistryKind = (rkBOOL, rkSTRING, rkEXPANDSTR, rkINTEGER, rkFLOAT, rkCURRENCY, rkBINARY_DATA, rkDATE, rkTIME, rkDATE_TIME);

 TRegistryKindResult = record
   AsBool: Boolean;
   AsString: string;
   AsInteger: Integer;
   AsFloat: Single;
   AsCurrency: Currency;
 end;

我在这里需要的是用通用婴儿车创建一个程序,接受任何类型的输入并将它们保存到注册表..
这是诀窍:

procedure TAppSettings.Save_Setting_ToRegistry(AKey, AItem_Setting: String;
    AValue: **UnknownType**; ARegKind: TRegistryKind);
var
  Reg: TRegIniFile;
begin
  Reg := TRegIniFile.Create(AKey);
  try
    case ARegKind of
      rkBOOL: Reg.WriteBool('', AItem_Setting, AValue);
      rkSTRING: Reg.WriteString('', AItem_Setting, AValue);
    end;

    Reg.CloseKey;
  finally
    Reg.Free;
  end;
end;

我应该为参数 AValue 做什么?有没有一种聪明的方法可以告诉我的 Delphi IDE 接受我在上面的 TRegistryKindResult 记录中定义的 5 种输入?

这里有一个解决方案(以前用过,现在没测试):

procedure TAppSettings.Save_Setting_ToRegistry(AKey, AItem_Setting: String;
    const AValue; ARegKind: TRegistryKind);
var
  Reg: TRegIniFile;
  VBool: Boolean absolute AValue;
  VString: String absolute AValue;
  VInteger: Integer absolute AValue;
  VFloat: Single absolute AValue;
  VCurrency: Currency absolute AValue;
begin
  Reg := TRegIniFile.Create(AKey);
  try
    case ARegKind of
      rkBOOL: Reg.WriteBool('', AItem_Setting, VBool);
      rkSTRING: Reg.WriteString('', AItem_Setting, VString);
      // Manage the other types...
    end;

    Reg.CloseKey;
  finally
    Reg.Free;
  end;
end;

单位System.RTTI为此提供类型TValue

procedure TAppSettings.Save_Setting_ToRegistry(AKey, AItem_Setting: string; AValue: TValue; ARegKind: TRegistryKind);
var
  Reg: TRegIniFile;
begin
  Reg := TRegIniFile.Create(AKey);
  try
    case ARegKind of
      rkBOOL:
        Reg.WriteBool('', AItem_Setting, AValue.AsBoolean);
      rkSTRING:
        Reg.WriteString('', AItem_Setting, AValue.AsString);
    end;

    Reg.CloseKey;
  finally
    Reg.Free;
  end;
end;

您可以使用 Variant:

procedure TAppSettings.Save_Setting_ToRegistry(AKey, AItem_Setting: String;
  AValue: Variant; ARegKind: TRegistryKind);
var
  Reg: TRegIniFile;
begin
  Reg := TRegIniFile.Create(AKey);
  try
    case ARegKind of
      rkBOOL: Reg.WriteBool('', AItem_Setting, AValue);
      rkSTRING: Reg.WriteString('', AItem_Setting, AValue);
      ...
    end;
    Reg.CloseKey;
  finally
    Reg.Free;
  end;
end;

老派的方法是使用 variants。然后,实际上,您甚至不需要 TRegistryKind 参数:

procedure SaveSetting(const AKey, ASetting: string; AValue: Variant);
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  try
    Reg.RootKey := HKEY_CURRENT_USER;
    if Reg.OpenKey(AKey, True) then
    begin
      case VarType(AValue) of
        varSmallint, varInteger, varShortInt, varByte, varWord:
          Reg.WriteInteger(ASetting, AValue);
        varCurrency:
          Reg.WriteCurrency(ASetting, AValue);
        varSingle, varDouble:
          Reg.WriteFloat(ASetting, AValue);
        varBoolean:
          Reg.WriteBool(ASetting, AValue);
        varString, varUString:
          Reg.WriteString(ASetting, AValue);
      else
        raise Exception.Create('Unsupported variant type.');
      end;
    end;
  finally
    Reg.Free;
  end;
end;

测试一下:

procedure TForm1.FormCreate(Sender: TObject);
begin
  SaveSetting('Software\Rejbrand\Test', 'intsetting', 123);
  SaveSetting('Software\Rejbrand\Test', 'cursetting', Currency(3.1415));
  SaveSetting('Software\Rejbrand\Test', 'fltsetting', Double(3.1415));
  SaveSetting('Software\Rejbrand\Test', 'boolsetting', True);
  SaveSetting('Software\Rejbrand\Test', 'strsetting', 'Hello, World!');
end;