是否可以在Delphi中将类型存储在变量中?

时间:2019-05-10 20:38:31

标签: delphi

我有三个类,例如(TMyClass1,TMyClass2和TMyClass3)。

我有一个函数,该函数将类型名称的字符串作为参数,然后实例化给定类型的类。现在我正在使用if语句,例如:

grid.arrange()

等等。

有没有一种方法可以将类型存储在变量中,以便更改将字符串链接到类型并避免使用它?

如果有帮助,MyClass1,MyClass2和MyClass3都将从另一个类继承...

1 个答案:

答案 0 :(得分:8)

看看RTL的RegisterClass()FindClass() / GetClass()函数,它们正是针对这种情况而设计的,例如:

const OffersSchema = require('../offers/offersModel').schema
const StoresSchema = require('../stores/storesModel').schema

OffersSchema.storeId = StoresSchema

const FeedsSchema = new Schema({ 
    offerId: OffersSchema,
    // ...other fields
})

然后您可以执行以下操作:

interface

uses
  ..., Classes;

type
  MyBase = class(TPersistent)
  public
    constructor Create; virtual;
  end;

  MyBaseClass = class of MyBase;

  MyClass1 = class(MyBase)
  public
    constructor Create; override;
  end;

  MyClass2 = class(MyBase)
  public
    constructor Create; override;
  end;

  MyClass3 = class(MyBase)
  public
    constructor Create; override;
  end;

...

function MakeMyClass(const Name: string): MyBase;

implementation

function MakeMyClass(const Name: string): MyBase;
begin
  Result := MyBaseClass(GetClass(Name)).Create;
end;

...

initialization
  RegisterClasses([MyClass1, MyClass2, MyClass3{, ...}]);

end.

缺点是类必须从var MyObj: MyBase; begin MyObj := MakeMyClass('MyClass1'); ... MyObj.Free; end; 派生。如果您不想使用TPersistent,或者只想使用不同的名称来创建类对象,则设置自定义工厂并不是很困难,例如通过使用TDictionary ,例如:

TPersistent

然后您可以执行以下操作:

interface

type
  MyBase = class
  public
    constructor Create; virtual;
  end;

  MyBaseClass = class of MyBase;

  MyClass1 = class(MyBase)
  public
    constructor Create; override;
  end;

  MyClass2 = class(MyBase)
  public
    constructor Create; override;
  end;

  MyClass3 = class(MyBase)
  public
    constructor Create; override;
  end;

...

function MakeMyClass(const Name: string): MyBase;

implementation

uses
  System.Generics.Collections, System.SysUtils;

var
  MyFactory: TDictionary<string, MyBaseClass>;

function MakeMyClass(const Name: string): MyBase;
begin
  Result := MyFactory[Name].Create;
end;

...

initialization
  MyFactory := TDictionary<string, TMyBaseCreateFunc>.Create;
  MyFactory.Add('xxx1', MyClass1);
  MyFactory.Add('xxx2', MyClass2);
  MyFactory.Add('xxx3', MyClass3);
finalization
  MyFactory.Free;
end.