En el artículo "Delphi Rtti fuerte: una discusión sobre la necesidad de comprender múltiples lenguajes de desarrollo", dije que utilicé el RTTI de Delphi para implementar una objetivación simple de conjuntos de datos. Este artículo presentará mi método de implementación en detalle.
Comencemos con un ejemplo simple: supongamos que hay un control de adodataset que se conecta a la base de datos Roswen, y SQL es:
Seleccionar * del empleado
Ahora necesita mostrar los cuatro campos EmployeeId, FirstName, LastName y Birth Fake en su contenido en ListView. El código tradicional es el siguiente:
Con ADODATAT1 comienza a abrir; FieldByName ('LastName'.Hay varios problemas principales aquí:
1. En primer lugar, hay muchos códigos que son muy detallados. Por ejemplo, FieldByname y Asxxx, etc., especialmente ASXXX, siempre debe recordar qué tipo de campo es, lo cual es fácil de cometer errores. Además, si algunos tipos incompatibles no se pueden convertir automáticamente, no se encontrarán errores hasta el tiempo de ejecución.
2. Debe procesar el movimiento de registro actual en el bucle usted mismo. Como el siguiente arriba, de lo contrario, se producirá un bucle muerto una vez que lo olvide.
3. Lo más importante es que el nombre del campo se pasa a través del parámetro de cadena. FieldByname, es probable que haga tal el problema solo aparecerá si se retrasa al cliente. Este tipo de nombres de campo incorrectos es fácil de suceder, especialmente cuando el programa usa múltiples tablas, es fácil confundir los nombres de campo de diferentes tablas.
En esta era gobernada por OO, cuando encontramos operaciones relacionadas con conjuntos de datos, todavía tenemos que caer en los detalles de la base de datos relacional mencionada anteriormente. Por supuesto, también hay una manera de deshacerse de ellos ahora, es decir, el mapeo O/R, pero el mapeo O/R es demasiado diferente de los métodos de desarrollo tradicionales, especialmente para algunas aplicaciones pequeñas, no hay necesidad de exagerar It. En este caso, todo lo que necesitamos es un esquema de objetivación de conjunto de datos simple.
Inspirado en Java y otros idiomas dinámicos, pensé en usar el poderoso RTTI de Delphi para implementar este simple esquema de objetivación del conjunto de datos. El siguiente es el código de aplicación objetivado del conjunto de datos que implementa las mismas funciones que el código tradicional:
Tipo TDSPEMPloyee = class (TMDataSetProxy) Propiedad publicada EmployeId: INTEGER ÍNDICE 0 Leer getInteger setInteger; SetVariant; (EmployeeD); EMP.Free;
El uso es muy simple. Lo más importante es definir primero una clase de proxy, que utiliza el atributo publicado para definir todos los campos, incluidos sus tipos, y luego puede manipular el conjunto de datos de manera objeto. Esta clase de proxy se deriva de TMDatasetProxy, que usa RTTI para implementar la asignación de las operaciones de atributos a las operaciones de campo. Las unidades de implementación de esta clase se explicarán en detalle a continuación.
En la superficie, hay una clase de proxy adicional que define el conjunto de datos, que parece tener más código, pero esto es algo único, especialmente cuando el programa necesita reutilizar la misma estructura de conjuntos de datos muchas veces, el código se hará. Además, la definición de esta clase de proxy es muy simple. Las funciones de acceso de atributos getxxx/setxxx utilizadas se implementan en la clase base tmdataSetProxy.
Ahora veamos el bucle correspondiente al código original:
1. FieldByName y ASXXX no son necesarios, y se han convertido en operaciones de atributos en las clases de proxy. It. Si se usa el tipo incorrecto, se informará un error durante la compilación.
2. Use un foreach para realizar un recorrido registrado, y ya no tiene que preocuparse por olvidar el bucle vicioso causado por el siguiente.
3. La mayor ventaja es que el nombre del campo se convierte en una propiedad, por lo que puede disfrutar de los beneficios de la verificación del nombre del campo en el momento de la compilación.
Ahora comience a discutir tmdatasetproxy. El código de su implementación es el siguiente:
(****************************************************** ********************* El proxy del conjunto de datos implementado con RTTI simplemente puede objetificar el conjunto de datos.Fecha: enero. ********************) Unidad MDSPCOMM; Clases de interfazos, DB, typinfo; type tmproplist = class (tobject) private fpropcount: Integer; (Aindex: Integer): Función de corto plazo; ; ; ; : TdataSet); ClassInfo)^. (FproPlist) luego freemem (fproPlist); TmproPlist.getPropName (aindex: integer): shorttring; begin resultado: = getProp (aindex)^. Name; end; {tmrefdataset} constructor tmdatasetproxy.create (adataset: tdataset); beginsing hereded create; ; end; procedimiento tmdatasetproxy.beginedit; begin if (fdataset.state <> dsedit) y (fdataset.state <> dsinsert) entonces fdataset.edit; end; procedimiento tmdatasetproxy.ended; comienza si (fdataset.state = dsedit) o (fdatasetetet. .State = dsinsert) entonces fdataset.post; end; function tmdataSetProxy.getInteger (aindex: integer): integer; : Integer): Double; Begin Result: = fDataset.FieldByName (fproplist.propnames [aindex]) .asfloat; end; function tmdataSetProxy.getString (aindex: integer): string; begin sten: = fdataset.fieldbyname (fpropoplist .propNames [ aindex]) .sastring; end; function tmdataSetProxy.getVariant (aindex: integer): variante; comienza el resultado: = fdataset.fieldbyname (fproplist.propnames [aindex]) .value; end; procedimiento tmdatasetproxy.setinteger (aindex, avalue: integerger; ); ]) .Asfloat: = Avalue; End; Procedimiento TMDatasetProxy.SetString (aindex: Integer; Avalue: String); BeginBeGinedit; aindex: entero; BEGAR ENDEDIT;
La clase TMProplist es una encapsulación de algunas funciones de la operación de atributo de RTTI. Su función es utilizar algunas funciones RTTI definidas por Delphi en la unidad TypInfo para implementar una clase derivada tpersistente para mantener su información de lista de propiedades publicada. La clase proxy obtiene el nombre del atributo a través de esta lista de atributos y finalmente opera a través de este nombre de atributo y los campos correspondientes en el conjunto de datos.
TMDatasetProxy es la clase base de la clase de proxy del conjunto de datos. La parte más importante es crear una lista de propiedades en la construcción posterior.
La operación de atributos solo implementa cuatro tipos de datos: entero, doble/flotante, cadena y variante. Si es necesario, puede obtener su propia clase base de proxy sobre esta base para implementar la implementación de otros tipos de datos. La implementación del reemplazo de la misma. Sin embargo, para los tipos que no se usan muy comúnmente, se recomienda que defina la clase de proxy real antes de implementarla. Por ejemplo, en el ejemplo anterior, suponiendo que TDATETIME no sea un tipo de uso común, puede hacer esto:
TDSPEMPLAYEE = class (TMDataSetProxy) Función protegida GetDateTime (constante constante: Integer): TDATETIME; Leer getString setString; (GetVariant (índice)); End; Procedimiento TDSPEMPloyee.SetDateTime (Índice de const
De esta manera, puede usar directamente la fecha de nacimiento como tipo TDATETIME.
Además, aprovechando esto, es posible proporcionar operaciones unificadas para algunos tipos de datos especiales personalizados.
Además, se llamó a BEGINET antes de todos los setxxx para evitar errores de tiempo de ejecución causados por olvidar usar DataSet.Edit.
Foreach se implementa para ser reutilizable. Además, se llama a EndEdit antes de enviar automáticamente los cambios.
Este esquema de objetivación del conjunto de datos es una solución muy simple. Esto se debe a que Delphi sigue siendo un lenguaje de desarrollo nativo después de todo. No hay dinámica, por lo que solo puede usar el método actual para registrarse.