delphi 我可以将对象转换为接口吗?

8dtrkrch  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(106)

我想将一个泛型对象转换为接口,但是我得到了一个“Operator not applied to this operators type”(这段代码是自定义组件的一部分,我在其中附加了不同的Entity类,以便它们打开)。

procedure OpenNewEntity(EntityClass: TClass);
begin
  if not Supports(EntityClass, IEntity) then
    raise Exception.Create(EntityClass.ClassName + ' is not an Entity');

  (EntityClass.Create as IEntity).Open;
end;

字符串
我尝试使用TClass代替实现接口的真实的类,因为我不想将该类的所有依赖项添加到这个单元中。
而不是TClass,我也尝试声明一个类引用来实现接口的类,但它说“Class type required”。

TEntityClass = class of IEntity;


我是否可以从实现接口的类中使用接口的新示例,而不向这些类添加依赖项?.

ljsrvy3e

ljsrvy3e1#

我想在大多数情况下不会这样工作,因为它总是调用TObject.Create,而不是在EntityClass中声明的任何构造函数。
更好的方法是使用泛型,它允许编译器捕获任何不支持IEntity的类:

type
  IEntity = interface
    ['{1B885059-58E5-4475-883F-6CD04FA01D40}']
    procedure Open;
  end;

type
  TEntityFactory = record
  public
    class function OpenNewEntity<T: constructor, IEntity>: IEntity; static;
  end;

class function TEntityFactory.OpenNewEntity<T>: IEntity;
begin
  Result := T.Create;
  Result.Open;
end;

字符串
施加到泛型类型T上的约束保证了类具有无参数构造函数并支持IEntity

**更新:**事实证明,变量中只有类类型,因此不能使用泛型方法。现在棘手的部分是以适当的方式创建Entity示例。基于TJSONUnMarshal.ObjectInstance()中的代码,过程的实现可能如下所示:

procedure OpenNewEntity(EntityClass: TClass);
var
  ctx: TRttiContext;
  entity: IEntity;
  instance: TObject;
  rType: TRttiType;
  mType: TRTTIMethod;
  metaClass: TClass;
begin
  ctx := TRttiContext.Create;
  rType := ctx.GetType(EntityClass);
  if rType <> nil then
    begin
    for mType in rType.GetMethods do
    begin
      if mType.HasExtendedInfo and mType.IsConstructor and (Length(mType.GetParameters) = 0) then
      begin
        // invoke
        metaClass := rType.AsInstance.MetaclassType;
        instance := mType.Invoke(metaClass, []).AsObject;
        if not Supports(instance, IEntity, entity) then
          raise Exception.Create(EntityClass.ClassName + ' is not an Entity');
        entity.Open;
        Exit;
      end;
    end;
    raise Exception.Create(EntityClass.ClassName + ' has no parameterless constructor');
  end;
  raise Exception.Create(EntityClass.ClassName + ' has no runtime type information');
end;

相关问题