Создание объектов Delphi во время выполнения на основе типа класса - PullRequest
1 голос
/ 29 марта 2010

Можно ли создавать объекты во время выполнения на основе его типа, вызывая метод.

Я пытаюсь достичь

var
  lForm1 : TForm;
  lForm2 : TForm;
begin
  CreateObjects([lForm1, lForm2]);
  // After this call I have the variables initialized and I can use them.
end;

Ответы [ 3 ]

8 голосов
/ 29 марта 2010

Недостаточно информации в вопросе.

Откуда происходит "тип" объектов формы (в вопросе)? Это просто имя типа? Как CreateObjects () обнаруживает тип, необходимый для каждого объекта?

Он не может быть получен из "типа" переданной ссылки на объект, поскольку это может быть (и почти наверняка будет, как в вашем примере) просто базовый тип, из которого в конечном итоге будет получен требуемый конкретный тип.

Без более подробной информации о ваших конкретных целях и ограничениях реализации полный, конкретный ответ невозможен.

Однако в общих чертах то, что вы ищете, может быть достигнуто с помощью комбинации виртуальных конструкторов и RegisterClass / FindClass , предоставляемых VCL.

Проще говоря, у вас будет базовый класс, который представляет общий конструктор, используемый для создания экземпляров ваших классов [для TComponent производных классов, он уже существует в виде Create () Владелец: TComponent ) конструктор].

Во время выполнения вы можете получить ссылку на любой (зарегистрированный) класс, используя FindClass ( 'TClassName' ) . Это вернет ссылку на класс, с помощью которого вы сможете вызвать соответствующий виртуальный конструктор:

  type
    TFoo = class ....
    TFooClass = class of TFoo;

    // etc


  var
    someClass: TFooClass;
    someObj: TFoo;
  begin
    someClass := TFooClass(FindClass('TFooDerivedClass'));
    someObj := someClass.Create(nil);
      :

Обратите внимание на то, что TFooDerivedClass является классом, который в конечном счете является производным от TFooClass (и предполагается, что для простоты, в свою очередь, происходит от TComponent и создается с владельцем NIL в этом случае). Классы, которые уже зарегистрированы в системе типов, можно найти с помощью FindClass () . Это включает в себя любой класс элемента управления или компонента, на который ссылается некоторый DFM в вашем приложении. Любые дополнительные классы, которые необходимо зарегистрировать, могут быть явно зарегистрированы с использованием RegisterClass () .

То, как ваше конкретное приложение идентифицирует типы вовлеченных объектов, и любое сопоставление имен типов с другой произвольной системой идентификации - это деталь реализации, о которой вы должны позаботиться.

1 голос
/ 29 марта 2010

Код непроверенной концепции:

function instantiate(var instancevars : array of tobject;
              const classtypes : array of TBaseClassType):boolean;

begin
  if (length(instancevars)=0) or (length(instancevars)<>length(classtypes)) then
    exit(false);
  for i:=0 to length(instancevars)-1 do
     instancevars[i]:=classtypes[i].create;
  result:=true;
end;

Тогда используйте

instantiate([lform1,lform2],[tform1,tform2]); 

чтобы все заработало.

Обратите внимание, что для работы "TBaseClassType" должен быть базовым классом для всех классов, используемых для этой функции, и иметь виртуальный конструктор (например, TPersistent?) Возможно, вам также необходимо исправить строку .create (например, добавить (NIL))

Вы не можете получить тип из переменной, информация доступна только во время компиляции.

0 голосов
/ 29 марта 2010

Цитирую ваш комментарий к ответу Хенка:

Это то, чего я не хочу делать. У меня есть много серверных методов, где я создаю много элементов управления во время выполнения, и мне было интересно, что создание объектов, как описано выше, уменьшило бы код.

Что вы подразумеваете под "много"?

Если вы имеете в виду множество компонентов одного и того же типа (например, «but1, but2, but3, .. but55: TButton;»), то измените свой код и используйте массив для представления ваших переменных - тогда вы можете сделать простой цикл для их создания.

Если вы имеете в виду множество компонентов разных типов (например: but1: TAnimatedButton; but2: TFlatButton; but3: T3DButton;), я не вижу никакого простого способа сделать это, и я думаю, что вы бы создали небольшой отладка ада больше всего на свете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...