Dalam artikel "Strong Delphi RTTI - Diskusi tentang perlunya memahami beberapa bahasa pengembangan", saya mengatakan bahwa saya menggunakan RTTI Delphi untuk menerapkan obyektifikasi set data sederhana. Artikel ini akan memperkenalkan metode implementasi saya secara rinci.
Mari kita mulai dengan contoh sederhana: Misalkan ada kontrol adodataset yang terhubung ke database Roswen, dan SQL adalah:
Pilih * dari karyawan
Sekarang Anda perlu menampilkan empat bidang karyawan, nama firstname, lastname, dan kelahiran dalam kontennya ke dalam ListView. Kode tradisional adalah sebagai berikut:
Dengan adodataSet1 mulai terbuka; sementara tidak EOF mulai dengan ListView1.add Mulai Keterangan: = InttoStr (FieldByName ('karyawan') .asinteger); Fieldbyname ('LastName') .astring);Ada beberapa masalah utama di sini:
1. Pertama -tama, ada banyak kode yang sangat bertele -tele. Misalnya, fieldbyname dan asxxx, dll., Terutama asxxx, Anda harus selalu mengingat jenis apa dari setiap bidang, yang mudah membuat kesalahan. Selain itu, jika beberapa tipe yang tidak kompatibel tidak dapat dikonversi secara otomatis, kesalahan tidak akan ditemukan sampai runtime.
2. Anda perlu memproses gerakan catatan saat ini dalam lingkaran sendiri. Seperti halnya di atas, jika tidak, loop mati akan terjadi begitu Anda melupakannya.
3. Yang paling penting adalah bahwa nama bidang dilewatkan melalui parameter string. Fieldbyname, kemungkinan akan membuat masalah seperti itu hanya akan muncul jika ditunda kepada pelanggan. Jenis nama bidang yang salah ini mudah terjadi, terutama ketika program menggunakan beberapa tabel, mudah untuk membingungkan nama bidang dari berbagai tabel.
Di era ini yang diperintah oleh OO, ketika kita menghadapi operasi yang terkait dengan set data, kita masih harus sering jatuh ke dalam rincian database relasional yang disebutkan di atas. Tentu saja, ada juga cara untuk menyingkirkan mereka sekarang, yaitu, pemetaan O/R, tetapi pemetaan O/R terlalu berbeda dari metode pengembangan tradisional, terutama untuk beberapa aplikasi kecil, tidak perlu membesar -besarkan itu.
Terinspirasi oleh Java dan bahasa dinamis lainnya, saya berpikir menggunakan RTTI Delphi yang kuat untuk mengimplementasikan skema objektifikasi dataset sederhana ini. Berikut ini adalah kode aplikasi yang diobjekkan dataset yang mengimplementasikan fungsi yang sama dengan kode tradisional:
Jenis TDSPETREYEE = Kelas (TMDATASETPROXY) PERKAYAAN PROPERTI PERKAITAN: INTEGER INDEX 0 BACA GetInteger Tulisan SetInteger; SetVariant; end; Prosedur TForm1.listClick (pengirim: TObject); var emp: TDSPEmployee; (Emproyeeid); emp. -Free;
Penggunaannya sangat sederhana. Yang paling penting adalah mendefinisikan kelas proxy terlebih dahulu, yang menggunakan atribut yang diterbitkan untuk menentukan semua bidang, termasuk tipe mereka, dan kemudian Anda dapat memanipulasi data yang ditetapkan dengan cara objek. Kelas proxy ini berasal dari TMDataSetProxy, yang menggunakan RTTI untuk mengimplementasikan pemetaan dari operasi atribut ke operasi lapangan. Unit implementasi kelas ini akan dijelaskan secara rinci di bawah ini.
Di permukaan, ada kelas proxy tambahan yang mendefinisikan set data, yang tampaknya memiliki lebih banyak kode, tetapi ini adalah hal satu kali, terutama ketika program perlu menggunakan kembali struktur set data yang sama berkali-kali, kode tersebut akan dibuat. Terlebih lagi, definisi kelas proxy ini sangat sederhana. Fungsi akses atribut GetXXX/SETXXX yang digunakan semuanya diimplementasikan di kelas dasar tmdatasetproxy.
Sekarang mari kita lihat loop yang sesuai dengan kode asli:
1. Fieldbyname dan ASXXX tidak diperlukan, dan mereka telah menjadi operasi atribut di kelas proxy. itu. Jika jenis yang salah digunakan, kesalahan akan dilaporkan selama kompilasi.
2. Gunakan foreach untuk melakukan traversal rekaman, dan tidak perlu lagi khawatir melupakan lingkaran setan yang disebabkan oleh selanjutnya.
3. Keuntungan terbesar adalah bahwa nama lapangan menjadi properti, sehingga Anda dapat menikmati manfaat verifikasi nama lapangan pada waktu kompilasi.
Sekarang mulailah membahas tmdatasetproxy. Kode implementasinya adalah sebagai berikut:
(*********************************************** ********************** Proxy Dataset Diimplementasikan dengan RTTI dapat dengan mudah menjadi obyektifkan dataset.Tanggal: Jan.28-05 *************************************** ******************) Unit MDSPCOMM; Antarmuka Kelas, DB, Typinfo; Type TMPropList = Class (Tobject) Private FPropCount: Integer; (AIndex): ShortString; ; Fungsi Virtual; Virtual; TDataSet); ClassInfo)^. Propcount; (Fproplist) kemudian freemem (fproplist); TMPropList.getPropName (AIndex: Integer): ShortString; Mulai Hasil: = GetProp (AIndex)^. Nama; end; {tmrefdataSet} mulai warisan tmdatasetproxy.create (adataset: tdataset); mulai warisan; ; end; Prosedur tmdatasetproxy.beginedit; mulai jika (fdataset.state <> dsedit) dan (fdataset.state <> dsinsert) kemudian fdataset.edit; end; prosedur tmdataSetproxy.Endentit; mulai jika (fdataSet.State = dseDedit) oredit; ordedit; .State = dsinsert) kemudian fdataset.post; end; function tmdatasetproxy.getInteger (aindex: integer): integer; : Integer): ganda; mulai hasil: = fdataset.fieldbyname (fproplist.propnames [aIndex]) .asfloat; end; function tmdatasetproxy.getString (aIndex: integer): string; Hasil mulai: = fdataset.fieldbyname (fproplist. aindex]) .asstring; end; fungsi tmdatasetproxy.getVariant (aindex: integer): varian; mulai hasil: = fdataset.fieldbyname (fproplist.propnames [aindex]) .value; end; prosedur tmdataSetproxy.setinteger (avalue; avdatae (avdatasetproxy.setinteger (avalue; avdatae (aVdataSetRoxy.setinteger (avdatae; ); ) .Asfloat: = avalue; end; prosedur tmdataSetproxy.setstring (aindex: integer; avalue: string); begegeGinedit; AIndex: Avalue; Mulai endedit;
Kelas TMPropList adalah enkapsulasi beberapa fungsi operasi atribut RTTI. Fungsinya adalah menggunakan beberapa fungsi RTTI yang ditentukan oleh Delphi di unit Typinfo untuk mengimplementasikan kelas turunan tpersistent untuk mempertahankan informasi daftar properti yang dipublikasikan. Kelas proxy memperoleh nama atribut melalui daftar atribut ini, dan akhirnya beroperasi melalui nama atribut ini dan bidang yang sesuai dalam dataset.
TMDataSetProxy adalah kelas dasar dari kelas proxy dataset. Bagian terpenting adalah membuat daftar properti di afterconstruction.
Pengoperasian atribut hanya mengimplementasikan empat tipe data: integer, ganda/float, string, dan varian. Jika perlu, Anda dapat memperoleh kelas dasar proxy Anda sendiri atas dasar ini untuk mengimplementasikan implementasi tipe data lainnya. Implementasi penggantiannya. Namun, untuk jenis yang tidak terlalu umum digunakan, disarankan agar Anda mendefinisikan kelas proxy yang sebenarnya sebelum mengimplementasikannya. Misalnya, dalam contoh sebelumnya, dengan asumsi bahwa tDateTime bukan tipe yang umum digunakan, Anda dapat melakukan ini:
TDSPEmployee = Class (TMDataSetProxy) Fungsi Protect GetDateTime (Const Index: Integer): TDATETIME; BACA GETRING TERBAIKI SETSTRING; (Getvariant (indeks)); end; prosedur TDSPEmployee.setDateTime (const index: integer; const value: tDateTime);
Dengan cara ini, Anda dapat secara langsung menggunakan Tanggal Lahir sebagai tipe TDATETIME.
Selain itu, memanfaatkan ini, dimungkinkan untuk menyediakan operasi terpadu untuk beberapa tipe data khusus khusus.
Juga, EmbinedIt dipanggil sebelum semua setxxx untuk menghindari kesalahan runtime yang disebabkan oleh lupa menggunakan dataset.Edit.
Foreach diimplementasikan untuk dapat digunakan kembali. Selain itu, EndEdit dipanggil sebelum di sebelahnya secara otomatis mengirimkan perubahan.
Skema objektifikasi dataset ini adalah solusi yang sangat sederhana. Ini karena Delphi masih merupakan bahasa pengembangan asli. Tidak ada dinamis, sehingga Anda hanya dapat menggunakan metode saat ini untuk mendaftar.