简体   繁体   English

使用Delphi在运行时中注册新类

[英]Register a New Class in runtime using Delphi

Is possible create (register) a new class in runtime using delphi. 可以在运行时使用delphi创建(注册)新类。

I have a Class called TMyForm, is possible create a new form derived from TMyForm but with new class type. 我有一个名为TMyForm的类,可以创建一个从TMyForm派生但具有新类类型的新表单。

i want something like this 我想要这样的东西

var
  Myform          : TMyForm;
  MyFormClassBase : TFormClass;
begin
  MyFormClassBase  := TFormClass(RegisterMyNewClass('TMyNewClass'));//obviously RegisterMyNewClass does not exist
  Myform := MyFormClassBase.Create(Application);
  Myform.Show;
end; 

i am using delphi 7 我正在使用delphi 7

UPDATE 1 更新1

I dont look create a new instance of the same base class, i need create an new class type in runtime derived from another class. 我不希望创建相同基类的新实例,我需要在运行时中从另一个类派生新的类类型

UPDATE 2 更新2

Thank you very much for your interest. 非常感谢您的关注。 but the purpose is a bit complex to explain (because my bad english). 但是解释的目的有点复杂(因为我的英语不好)。 I have a form that allows you to edit multiple master data tables, all these tables have the same fields code (an integer primary key) and description (a varchar field), they serve to define currencies, countries, projects, groups, etc. 我有一个表格,可让您编辑多个主数据表,所有这些表都具有相同的字段代码(整数主键)和描述(varchar字段),它们用于定义货币,国家,项目,组等。

as logic is the same for all these tables, so only need this form by passing as parameters the title of the table name , to manage these tables. 因为所有这些表的逻辑都是相同的,所以只需要通过将表名的标题作为参数传递来管理这些表,就需要这种形式。 something like this 像这样的东西

FormCurrency:= TMyForm.Create( 'Define currencys', 'CURRENCYTABLE') 
if ValidateAccess(FormCurrency) then 
FormCurrency.Show
else
FormCurrency.Close;



FormGroups:= TMyForm.Create( 'Define Groups', 'GROUPSTABLE') 
if ValidateAccess(FormGroups) then 
FormGroups.Show
else 
FormGroups.Close;

on the other hand I have a validation method (called ValidateAccess) that validates the users access to the forms using the form's class . 另一方面,我有一个验证方法(称为ValidateAccess),该方法使用表单的class来验证用户对表单的访问。 because of this if you use the same kind of form is restricted access to all the options like "define groups","define currencys", "define countrys" (which I do not want that to happen), because that i need to pass to the ValidateAccess method a diferent class. 因此,如果您使用相同的形式,则只能访问所有选项,例如“定义组”,“定义货币”,“定义国家”(我不希望这种情况发生),因为我需要通过ValidateAccess方法的另一个类。

I cannot rewrite the ValidateAccess method because exist many diferents forms already registered in the system. 我无法重写ValidateAccess方法,因为系统中已经存在许多不同的表单。

I dont want create a new form type and a new unit over and over just changing the title and the table to use. 我不想一遍又一遍地创建新的表单类型和新的单位,只是更改标题和要使用的表。

Thanks in Advance. 提前致谢。

I don't know if I get you right, but what I understand can be achieved in this way: 我不知道我是否正确,但是通过以下方式可以实现我的理解:

type
  TCurrencyForm = class(TMyForm);
  TGroupsForm = class(TMyForm);


FormCurrency:= TCurrencyForm.Create( 'Define currencys', 'CURRENCYTABLE') 
if ValidateAccess(FormCurrency) then 
FormCurrency.Show
else
FormCurrency.Close;

FormGroups:= TGroupsForm.Create( 'Define Groups', 'GROUPSTABLE') 
if ValidateAccess(FormGroups) then 
FormGroups.Show
else 
FormGroups.Close;

In your ValidateAccess method (assuming the parameter is named Form ) you can check something like: 在您的ValidateAccess方法中(假设参数名为Form ),您可以进行如下检查:

if Form is TCurrencyForm then
else if Form is TGroupsForm then 

If you don't have access to the new form class declarations you can use Form.ClassName instead. 如果您无权访问新的表单类声明,则可以改用Form.ClassName。

It looks like Uwe managed to solve your problem. 看起来Uwe设法解决了您的问题。 I should just state for the record that it is possible to add new class types at runtime. 我只想说明一下,可以在运行时添加新的类类型。 Classes are defined by their class reference, which is a pointer to a VMT (Virtual Method Table), and if you know how VMTs are laid out you can create one of your own. 类由其类引用定义,该类引用是指向VMT(虚拟方法表)的指针,如果您知道VMT的布局方式,则可以创建自己的类。 I did a session on it at CodeRage last year. 去年,我在CodeRage上做了一个会议。 Unfortunately, the audio quality sucked. 不幸的是,音频质量糟透了。 :( :(

Of course, this isn't much use to you unless you have to create classes whose definition is not available at compile time, for example if you're using a scripting engine. 当然,除非您必须创建其定义在编译时不可用的类(例如,如果您使用脚本引擎),否则这对您没有太大用处。 When all the information you need is available at compile time, go with something like what Uwe described. 当您需要的所有信息在编译时可用时,请使用Uwe所描述的内容。

Why do you need to create a new subclass of the form? 为什么需要创建表单的新子类? You cannot change anything about that new class to make it different from the existing class at runtime. 您不能在运行时更改有关该新类的任何内容以使其与现有类有所不同。 ie you cannot add new methods or properties. 即您不能添加新的方法或属性。

I suspect that you have made the mistake of thinking that one form class can have only one instance. 我怀疑您错误地认为一个表单类只能有一个实例。 But this is not the case. 但这种情况并非如此。 You can create as many instances of a form as you wish: 您可以根据需要创建任意多个表单实例:

var
  formA : TMyForm;
  formB : TMyForm;
begin
  formA := TMyForm.Create(Application);
  formB := TMyForm.Create(Application);
  formA.Show;
  formB.Show;
end;

If this isn't what you require, you will need to provide more information about just what exactly it is you are trying to achieve. 如果这不是您所需要的,那么您将需要提供有关您要实现的目标的更多信息。

IIUC, you can have something like this: IIUC,您可以有这样的事情:

TmyForm = class... //your normal form
...
public
  property Title: string read FTitle write SetTitle;
  property FormKind: TFormKind read FFormKind write SetFormKind;
  function ValidateAccess: boolean;
  ...
end;

Where TFormKind = (fkCurrency, fkCountry, ...); 其中TFormKind = (fkCurrency, fkCountry, ...);

And in your SetTitle will also set the form's caption, in your SetFormKind you will do your coressponding initialization(s) if necessary whereas in ValidateAccess you will handle (most probably in a case ) the different situations according to the value of FFormKind . 并且在您的SetTitle还将设置表单的标题,在您的SetFormKind您将根据需要进行核心响应的初始化,而在ValidateAccess您将根据FFormKind的值处理(最有可能的case )不同情况。

And to use it: 并使用它:

myForm:=TmyForm.Create(Application); //since we'll free it the owner can be also 'nil'
myForm.Title:='Boo!';
myForm.Kind:=fkCurrency;
if myForm.ValidateAccess then
  myForm.ShowModal; //btw your 'if' structure is a little bit 'odd' to say at least. You don't need to call Close on a form which isn't showing

myForm.Free; //get rid of it. - of course this applies if we created it. Not applicable if you use 'Show' only, of course.

However perhaps you'll find better to separate the layers and have a different class to handle the validation, according to the form's properties etc. 但是,也许您会发现更好地分离各层,并根据表单的属性等使用不同的类来处理验证。

I have similar problem, and find some runtime solution. 我有类似的问题,并找到一些运行时解决方案。 Only request is that MyForm already created in runtime. 唯一的要求是MyForm已在运行时创建。

 var vOldForm,vNewForm:TObject;
begin
  vOldForm:=Application.FindComponent('MyForm');
  If vOldForm<>nil then
     vNewForm:=TFormClass(vOldForm.ClassType).Create(Application);
  If vNewForm is vOldForm.ClassType then (vNewForm as TForm).Show;
end;

Delphi is a 'static' language, so you cannot create a new type (or class) at run time. Delphi是一种“静态”语言,因此您无法在运行时创建新的类型(或类)。 You can do this in some 'dynamic' languages, like Python. 您可以使用某些“动态”语言(例如Python)来执行此操作。

If you are trying to create a new form, populated with different controls, you can do this, but you need to create each individual control, make the form it's parent (and owner) and set it's position and caption etc. 如果要创建一个新表单,并用不同的控件填充,则可以执行此操作,但是您需要创建每个单独的控件,将其作为父控件(和所有者),并设置其位置和标题等。

procedure TForm1.Button1Click(ASender: TObject);
var
  LForm: TForm;
  LLabel: TLabel;
begin
  LForm := TForm.Create(nil);
  try

    LForm.Width := 100;
    LForm.Height := 100;

    LLabel := TLabel.Create(LForm);
    LLabel.Parent := LForm;
    LLabel.Caption := 'Hello World!';

    LForm.ShowModal;

  finally
    FreeAndNil(LForm);
  end;
end;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM