如何将 class 引用 (metaclass) 作为参数传递给程序?
How to pass class reference (metaclass) as a parameter in procedure?
有两个对象:TFoo
、TFoo2
。
还有一个class参考:TFooClass = class of TFoo;
两者都是TPersistent
的后代。
他们有自己的构造函数:
type
TFoo = class(TPersistent)
private
FC:Char;
public
constructor Create; virtual;
published
property C:Char read FC write FC;
end;
TFoo2 = class(TFoo)
public
constructor Create; override;
end;
TFooClass = class of TFoo;
...
constructor TFoo.Create;
begin
inherited Create;
C :=' 1';
end;
constructor TFoo2.Create;
begin
inherited Create;
C := '2';
end;
我想从一个字符串创建一个 TFoo2
对象,这实际上是它的 class 名称:'TFoo2'
这是程序,运行良好:
procedure Conjure(AClassName:string);
var
PClass : TPersistentClass;
p :TPersistent;
begin
PClass := TPersistentClass(FindClass(AClassName))
p := TFooClass(PClass).Create; // <-- here is called appropriate constructor
end;
现在,我想要类似的对象,例如:TBobodo
、TBobodo2
。
当然还有 class 参考:TBobodoClass = class of TBobodo;
等等...
现在,如何将 class 引用作为参数传递到过程中,以确保调用正确的构造函数?
procedure Conjure(AClassName:string; ACLSREF: ???? ); // <-- something like that
var
PClass : TPersistentClass;
p :TPersistent;
begin
PClass := TPersistentClass(FindClass(AClassName))
p := ACLSREF(PClass).Create; // <-- something like that
end;
可能吗?
Delphi 7. 元类引用必须在编译时在调用站点显式显示,而不是在运行时处理。
在 Delphi 2009 年及以后,您 可能 1 可以使用 Generics 做一些事情,例如:
1: 我自己还没试过
type
TConjureHelper = class
public
class procedure Conjure<TClassType>(const AClassName: string);
end;
class procedure TConjureHelper.Conjure<TClassType>(const AClassName: string);
var
PClass : TPersistentClass;
p : TPersistent;
begin
PClass := TPersistentClass(FindClass(AClassName));
p := TClassType(PClass).Create;
...
end;
...
TConjureHelper.Conjure<TFooClass>('TFoo2');
TConjureHelper.Conjure<TBobodoClass>('TBobodo2');
...
但是Delphi7肯定不支持泛型
我遇到了同样的问题,经过一番努力,我找到了一个非常简单的解决方案:metaclass 正是为此目的而发明的!
在您的情况下,您可以将 metaclass 作为参数传递并直接使用它,而无需繁琐的查找 class 和类型转换。
type
TFooClass = class of TFoo;
procedure Conjure(aFooClass : TFooClass); // <-- something like that
var
p :TPersistent;
begin
p := aFooClass.Create; // it will work!
end;
通过调用,您只需使用:
Conjure(TFoo); // <- for Foo class or
Conjure(TFoo2); // <- for Foo2 class and so on
有两个对象:TFoo
、TFoo2
。
还有一个class参考:TFooClass = class of TFoo;
两者都是TPersistent
的后代。
他们有自己的构造函数:
type
TFoo = class(TPersistent)
private
FC:Char;
public
constructor Create; virtual;
published
property C:Char read FC write FC;
end;
TFoo2 = class(TFoo)
public
constructor Create; override;
end;
TFooClass = class of TFoo;
...
constructor TFoo.Create;
begin
inherited Create;
C :=' 1';
end;
constructor TFoo2.Create;
begin
inherited Create;
C := '2';
end;
我想从一个字符串创建一个 TFoo2
对象,这实际上是它的 class 名称:'TFoo2'
这是程序,运行良好:
procedure Conjure(AClassName:string);
var
PClass : TPersistentClass;
p :TPersistent;
begin
PClass := TPersistentClass(FindClass(AClassName))
p := TFooClass(PClass).Create; // <-- here is called appropriate constructor
end;
现在,我想要类似的对象,例如:TBobodo
、TBobodo2
。
当然还有 class 参考:TBobodoClass = class of TBobodo;
等等...
现在,如何将 class 引用作为参数传递到过程中,以确保调用正确的构造函数?
procedure Conjure(AClassName:string; ACLSREF: ???? ); // <-- something like that
var
PClass : TPersistentClass;
p :TPersistent;
begin
PClass := TPersistentClass(FindClass(AClassName))
p := ACLSREF(PClass).Create; // <-- something like that
end;
可能吗?
Delphi 7. 元类引用必须在编译时在调用站点显式显示,而不是在运行时处理。
在 Delphi 2009 年及以后,您 可能 1 可以使用 Generics 做一些事情,例如:
1: 我自己还没试过
type
TConjureHelper = class
public
class procedure Conjure<TClassType>(const AClassName: string);
end;
class procedure TConjureHelper.Conjure<TClassType>(const AClassName: string);
var
PClass : TPersistentClass;
p : TPersistent;
begin
PClass := TPersistentClass(FindClass(AClassName));
p := TClassType(PClass).Create;
...
end;
...
TConjureHelper.Conjure<TFooClass>('TFoo2');
TConjureHelper.Conjure<TBobodoClass>('TBobodo2');
...
但是Delphi7肯定不支持泛型
我遇到了同样的问题,经过一番努力,我找到了一个非常简单的解决方案:metaclass 正是为此目的而发明的! 在您的情况下,您可以将 metaclass 作为参数传递并直接使用它,而无需繁琐的查找 class 和类型转换。
type
TFooClass = class of TFoo;
procedure Conjure(aFooClass : TFooClass); // <-- something like that
var
p :TPersistent;
begin
p := aFooClass.Create; // it will work!
end;
通过调用,您只需使用:
Conjure(TFoo); // <- for Foo class or
Conjure(TFoo2); // <- for Foo2 class and so on