我有无约束的通用类型Atomic,它实现一个初始化器(在我的
previous question中的细节).
type Atomic<T> = class type TFactory = reference to function: T; class function Initialize(var storage: T; factory: TFactory): T; end;
现在我想编写简化的初始化函数,它将从T中获取类型信息(只要typeof(T)为tkClass),并使用默认构造函数创建新实例(如有必要).
可悲的是,这失败了:
class function Atomic<T>.Initialize(var storage: T): T; begin if not assigned(PPointer(@storage)^) then begin if PTypeInfo(TypeInfo(T))^.Kind <> tkClass then raise Exception.Create('Atomic<T>.Initialize: Unsupported type'); Result := Atomic<T>.Initialize(storage,function: T begin Result := TClass(T).Create; // <-- E2571 end); end; end;
编译器报告错误E2571类型参数’T’没有类或接口约束.
我如何欺骗编译器创建T类的实例?
解决方法
您可以使用新的Delphi Rtti来完成此任务.给定解决方案的缺点是,如果构造函数未命名为Create,则它将无法正常工作.如果你需要让它一直工作,只需枚举你的类型方法,检查它是否是一个构造函数,并有0个参数,然后调用它.在德尔福XE工作.示例代码:
class function TTest.CreateInstance<T>: T; var AValue: TValue; ctx: TRttiContext; rType: TRttiType; AMethCreate: TRttiMethod; instanceType: TRttiInstanceType; begin ctx := TRttiContext.Create; rType := ctx.GetType(TypeInfo(T)); AMethCreate := rType.GetMethod('Create'); if Assigned(AMethCreate) and rType.IsInstance then begin instanceType := rType.AsInstance; AValue := AMethCreate.Invoke(instanceType.MetaclassType,[]);// create parameters Result := AValue.AsType<T>; end; end;
更新解决方案:
class function TTest.CreateInstance<T>: T; var AValue: TValue; ctx: TRttiContext; rType: TRttiType; AMethCreate: TRttiMethod; instanceType: TRttiInstanceType; begin ctx := TRttiContext.Create; rType := ctx.GetType(TypeInfo(T)); for AMethCreate in rType.GetMethods do begin if (AMethCreate.IsConstructor) and (Length(AMethCreate.GetParameters) = 0) then begin instanceType := rType.AsInstance; AValue := AMethCreate.Invoke(instanceType.MetaclassType,[]); Result := AValue.AsType<T>; Exit; end; end; end;
并称之为:
var obj: TTestObj; begin obj := TTest.CreateType<TTestObj>;