如何将一个对象转换为通用的对象? [英] How can I cast an object to a generic?

查看:124
本文介绍了如何将一个对象转换为通用的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将返回的基础对象转换为特定的泛型类型。下面的代码应该可以工作,但是会产生一个内部的编译器错误,还有另一种方法吗?

I'm trying to cast a returned base object to it's specific generic type. The code below should work I think but generates an internal compiler error, is there another way to do this?

type
  TPersistGeneric<T> = class
  private
  type
    TPointer = ^T;
  public
    class function  Init : T;
  end;

class function  TPersistGeneric<T>.Init : T;
var
  o : TXPersistent; // root class
begin
  case PTypeInfo(TypeInfo(T))^.Kind of
    tkClass : begin
                // xpcreate returns txpersistent, a root class of T
                o := XPCreate(GetTypeName(TypeInfo(T))); // has a listed of registered classes
                result := TPointer(pointer(@o))^;
              end;
    else
      result := Default(T);
  end;
end;


推荐答案

我正在使用类型转换助手类,类型转换,并且还检查两个类是否兼容。

I'm using a typecast helper class that does the typecasts and also checks if the two classes are compatible.

class function TPersistGeneric<T>.Init: T;
var
  o : TXPersistent; // root class
begin
  case PTypeInfo(TypeInfo(T))^.Kind of
    tkClass : begin
                // xpcreate returns txpersistent, a root class of T
                o := XPCreate(GetTypeName(TypeInfo(T))); // has a listed of registered classes
                Result := TTypeCast.DynamicCast<TXPersistent, T>(o);
              end;
    else
      result := Default(T);
  end;

这是课程:

type
  TTypeCast = class
  public
    // ReinterpretCast does a hard type cast
    class function ReinterpretCast<ReturnT>(const Value): ReturnT;
    // StaticCast does a hard type cast but requires an input type
    class function StaticCast<T, ReturnT>(const Value: T): ReturnT;
    // DynamicCast is like the as-operator. It checks if the object can be typecasted
    class function DynamicCast<T, ReturnT>(const Value: T): ReturnT;
  end;

class function TTypeCast.ReinterpretCast<ReturnT>(const Value): ReturnT;
begin
  Result := ReturnT(Value);
end;

class function TTypeCast.StaticCast<T, ReturnT>(const Value: T): ReturnT;
begin
  Result := ReinterpretCast<ReturnT>(Value);
end;

class function TTypeCast.DynamicCast<T, ReturnT>(const Value: T): ReturnT;
var
  TypeT, TypeReturnT: PTypeInfo;
  Obj: TObject;
  LClass: TClass;
  ClassNameReturnT, ClassNameT: string;
  FoundReturnT, FoundT: Boolean;
begin
  TypeT := TypeInfo(T);
  TypeReturnT := TypeInfo(ReturnT);
  if (TypeT = nil) or (TypeReturnT = nil) then
    raise Exception.Create('Missing Typeinformation');
  if TypeT.Kind <> tkClass then
    raise Exception.Create('Source type is not a class');
  if TypeReturnT.Kind <> tkClass then
    raise Exception.Create('Destination type is not a class');

  Obj := TObject(Pointer(@Value)^);
  if Obj = nil then
    Result := Default(ReturnT)
  else
  begin
    ClassNameReturnT := UTF8ToString(TypeReturnT.Name);
    ClassNameT := UTF8ToString(TypeT.Name);
    LClass := Obj.ClassType;
    FoundReturnT := False;
    FoundT := False;
    while (LClass <> nil) and not (FoundT and FoundReturnT) do
    begin
      if not FoundReturnT and (LClass.ClassName = ClassNameReturnT) then
        FoundReturnT := True;
      if not FoundT and (LClass.ClassName = ClassNameT) then
        FoundT := True;
      LClass := LClass.ClassParent;
    end;
    //if LClass <> nil then << TObject doesn't work with this line
    if FoundT and FoundReturnT then
      Result := ReinterpretCast<ReturnT>(Obj)
    else
    if not FoundReturnT then
      raise Exception.CreateFmt('Cannot cast class %s to %s',
                                [Obj.ClassName, ClassNameReturnT])
    else
      raise Exception.CreateFmt('Object (%s) is not of class %s',
                                [Obj.ClassName, ClassNameT]);
  end;
end;

这篇关于如何将一个对象转换为通用的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆