我有一个线程库,它有三个不同方法类型的构造函数。我希望它们合并为一个逻辑,以便在构造函数中区分它们。可能吗?由于值TValue
等等,方法类型是否有类似的东西?
我现在支持以下类型;
TAgThreadMethod1 = procedure of object;
TAgThreadMethod2 = procedure;
TAgThreadMethod3 = procedure(const AThread: TAgThread) of object;
并且构造函数是这样的:
constructor Create(const AOnRun: TAgThreadMethod1); overload; virtual;
constructor Create(const AOnRun: TAgThreadMethod2); overload; virtual;
constructor Create(const AOnRun: TAgThreadMethod3); overload; virtual;
作为参考,我不希望用户能够在构造完成后稍后更改worker方法。因此,如果存在可以在单个构造函数中执行此类操作的解决方案,也欢迎使用;
constructor Create
(const AOnRun: [Some type which can hold arbitrary method types]);
begin
// code to identify the method contained in AOnRun.
// if supported, assign it the correct handler.
end;
答案 0 :(得分:5)
没有任何好的方法可以做到这一点,因为方法指针的整个要点稍后会被调用,除非你知道它的签名,否则你不能这样做。因此,失去签名之间的区别非常适得其反。
如果你只想在对象中存储一种类型的调用,你可以让三个构造函数分别创建一个带有统一签名的匿名方法,该签名包含对这三种类型的调用,而只是存储而不是必须存储处理多种不同的方法类型。但是,你所要求的,特别是,不会起作用。
答案 1 :(得分:4)
我认为你能做的最好的事情就是有一个构造函数,它接受程序类型的最一般形式。那是TProc<TAgThread>
。这将是主构造函数,唯一的虚构造函数。然后,您可以将其他构造函数委托给主构造函数。
总结一下,declaration in SysUtils
是:
type
TProc<T> = reference to procedure(Arg1: T);
所以你的主构造函数是:
constructor Create(AOnRun: TProc<TAgThread>); overload; virtual;
其他构造函数不是虚拟的,可能如下所示:
constructor Create(AOnRun: TAgThreadMethod1); overload;
实施为:
constructor TMyClass.Create(AOnRun: TAgThreadMethod1);
begin
Create(
procedure(Thread: TAgThread)
begin
AOnRun();
end;
);
end;
主构造函数(虚拟构造函数)完成所有工作。其他构造函数(非虚函数)调整其参数以适合主构造函数的构造函数。
答案 2 :(得分:1)
这是可能的,但不仅仅是TValue。
您可以将其作为TRttiMethod传递,而不是传递方法本身:MyRegisterMethod(TRttiContext.GetType(TMyClassType).GetMethod('MyMethodName'));
如果要传递所有构造函数,则需要使用如下循环:
for MyMethod in TRttiContext.GetType(TMyClassType).GetMethods do
if MyMethod.IsConstructor then // As in your example you only want constructors
MyRegisterMethod(MyMethod);
稍后,您可以像这样调用此方法:MyRegisteredMethod.Invoke(nil, MyMethodParams)
。 MyMethodParams是一个TValue数组,您需要提供它。这可以存储在TValue本身中(尽管将它们存储在TArray中可能更容易)。请注意,在类方法的情况下,您只想在调用中使用nil
。
如果您想确保参数正常,可以通过在MyRttiMethod.GetParameters
中查找它们来验证它们,并将它们的实际类型与TValue数组中实际类型的TValue进行比较。这也可用于找到正确的方法。