Histórico de atualização: No.1
Horário de atualização: 01-11-2001 20:09
Atualizado por: Musicwind®
Nota de atualização: primeiro rascunho concluído.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~
resumo:
Este artigo discute como exportar classes em uma DLL - muitas subclasses baseadas em uma classe abstrata específica. Esta tecnologia utiliza a ideia de polimorfismo, permitindo-nos obter efeitos semelhantes aos plug-ins.
Leitores pretendidos:
Compreender o conceito de polimorfismo; compreender o conceito de metaclasse.
Dificuldade técnica:
6/10 .
Para exportar uma classe de uma DLL, a primeira coisa que você deve pensar é usar o pacote bpl. Uma desvantagem deste método é que o usuário deve saber quais classes estão contidas no pacote, o que significa que o nome da classe deve ser conhecido - isto é uma limitação em certo sentido. Imagine uma situação onde o usuário define uma camada inferior. classe abstrata e, em seguida, muitas classes de aplicativos (concretas class), então, para o usuário, ele espera poder usar essas classes sem conhecer as classes específicas - parece um pouco misterioso dizer isso, mas a situação real é de fato o caso, porque não pode ser prevista ao definir o abstrato classes Quantas classes específicas haverá no futuro? Então, que tipo de tecnologia será necessária para atender a essa demanda?
Na verdade, a dificuldade técnica de implementação não é muito difícil - o autor aqui dedica a sua experiência prática a todos, como forma de atrair novas ideias, e espera ver outros métodos melhores!
A seguir, primeiro apresentamos alguns conhecimentos básicos envolvidos neste método e, em seguida, usamos um exemplo para ilustrar a implementação específica.
1. Conceitos básicos
Metaclasse (metaclasse), também chamada de tipo de referência de classe (tipo de referência de classe), pode ser considerada um tipo de classe, e o valor de uma variável declarada com este tipo representa uma classe. por exemplo:
tipo
TClass = Classe do TObject;
Isso declara um tipo de metaclasse. Então você pode ter declarações de variáveis como esta:
Var
ClasseA: ClasseT;
Então, você pode usá-lo assim:
AClass := TObject;
ou:
AClass := TButton;
ou:
AClass := TForm;
etc.
Como TClass é uma metaclasse do tipo TObject, e TButton, TForm, etc. são todos derivados de TObject, valores como TButton e TForm são aceitáveis para AClass.
Então, podemos usar a ideia de polimorfismo e usar de forma flexível a variável de classe AClass. Este também é o conhecimento básico para a implementação específica abaixo.
2. Implementação específica
O primeiro passo é criar uma classe abstrata:
Usamos uma declaração tão simples. A classe abstrata fornece apenas um método abstrato, mas não afeta nossa descrição do problema:
TMyBaseForm = Classe(TForm)
Protegido
função GetTitle: pchar virtual;
fim;
MyBaseFormClass = Classe de TMyBaseForm;
Não vamos discutir quantos métodos e interfaces práticas essa classe abstrata oferece, porque o que queremos discutir é uma viabilidade técnica. Suponha que a intenção original do autor ao definir essa interface seja obter qualquer número de títulos alterados e que o valor de retorno específico de GetTitle precise ser implementado por subclasses. Além disso, o autor também espera que o código da subclasse possa ser implementado em DLL e separado do programa principal - este método tem um sabor de plug-in, e também pode ser capaz de realizar alguns recursos do Plug&Play - não é bem atraente? Então, o que você deve fazer a seguir?
Primeiro, o programa principal e o programa DLL devem incluir as unidades declaradas acima. Em seguida, o programa principal é responsável por implementar um driver - carregar dinamicamente a DLL e carregar dinamicamente as classes e a DLL é responsável pela implementação das subclasses.
Vamos falar sobre Dll primeiro.
O segundo passo é exportar a subclasse em DLL :
Projetamos as duas funções exportadas a seguir:
1. função GetClassCount: inteiro;
Diga ao chamador que existem várias subclasses nesta DLL;
2. função GetClassTypeByIndex(const iIndex: inteiro;
var ClassType: MyBaseFormClass): WordBool;
Obtenha uma subclasse específica por índice. Observe que o tipo de ClassType aqui é MyBaseFormClass, o que indica que seu valor será uma classe definida herdada de TMyBaseForm.
Aqui está uma possível implementação deles:
função GetClassCount: inteiro;
começar
result := 3; //Indica que 3 classes são exportadas nesta DLL
fim;
função GetClassTypeByIndex(const iIndex: inteiro;
var ClassType: MyBaseFormClass): WordBool;
começar
resultado := Verdadeiro;
caso iÍndice de
0: ClassType := TFrmTest1;
1: ClassType := TFrmTest2;
2: ClassType := TFrmTest3;
outro
resultado := Falso;
fim;
fim;
Obviamente, as unidades onde TFrmTest1, TFrmTest2 e TFrmTest3 estão localizados devem ser incluídas na lista de uso da unidade. A implementação do TFrmTest1 pode ser assim:
TFrmTest1 = Classe(TMyBaseForm)
protegido
função GetTitle: substituição de PChar;
fim;
função TFrmTest1.GetTitle: Pchar;
começar
resultado:= 'Olá do TFrmTest1';
fim;
Por fim, não se esqueça de adicionar GetClassCount e GetClassByIndex à lista de Exportações. Então, ao construir o projeto DLL, marque "usar pacote de tempo de execução" no pacote de opções do projeto. As razões específicas serão discutidas mais tarde.
Neste ponto, o trabalho na DLL chegou ao fim.
A terceira etapa é a implementação do mecanismo principal do driver do programa:
Esta etapa é relativamente fácil - nada mais é do que carregar dinamicamente a DLL, depois chamar a função GetClassCount e, em seguida, chamar GetClassByIndex. Código chave:
Var AClass: TMyBaseClass;
AForm: TMyBaseForm;
Eu, iCount: inteiro;
blResultado: Booleano;
começar
//Omita a parte sobre o carregamento da biblioteca dinâmica, assumindo que FPGetClassProc aponta para a função GetClassCount e FPGetClassByIndexProc aponta para GetClassByIndex, então:
iCount := FPGetClassProc;
para I := 0 para iCount ?C 1 do
começar
AClass := FPGetClassByIndex(I, blResult);
se blResult então
começar
AForm := AClass.Create(aplicativo);
AForm.Caption := AForm.GetTitle;
AForm.Mostrar;
fim;
fim;
//…
fim;
Observe que, semelhante ao DLL, você também precisa optar por usar o pacote de tempo de execução ao criar o arquivo de saída. Isso ocorre porque não usar o pacote de tempo de execução resultará em múltiplas cópias da mesma classe na memória, portanto, usar o operador Is nelas retornará um resultado False.
Musicwind®@HangZhou.Zhejiang.China
01/11/2001
Mais artigos
[ Fim do artigo]