14 Aralık 2023 Perşembe

Örnek DI uygulaması 4-Frame'leri standart bir frame'den türetmek

 Bu zamana kadar gördüğümüz gibi, her frame'de aynı işlemleri yapıyoruz. Bunları tek bir ancestor (ata) TFrame'de yapsak ve diğer tüm frame'leri ondan türetsek nasıl olur;

Önce View.Inventories ve View.Customers unit'lerini projeden çıkaralım. Bunları ve dfm dosyalarını başka bir klasöre taşıyalım.

Daha sonra yeni bir TFrame unit'i ekleyelim ve bunu View.MyBaseFrame.pas adıyla kaydedelim. İçindeki frame'e frameMyBase adı verelim, üzerine 2 adet panel koyalım. Panel2'nin Align=alBottom ve Panel1'in Align=alClient yapalım. Her ikisinin de BevelOuter=bvNone ve Caption={boş} yapalım.

Panel1 üzerine bir DBGrid ve bir de DataSource koyalım. DBGrid'in Align=alClient, DataSource=DataSource1 yapalım. Ayrıca DBGrid'in ReadOnly=True, Options.RowSelect=True yapalım.

TframeMyBase şu şekilde olsun,

unit View.MyBaseFrame;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Data.DB,
  Vcl.Grids, Vcl.DBGrids,
  uInterfaces,
  Spring.Container;

type
  TframeMyBase = class(TFrame)
    Panel2: TPanel;
    Panel1: TPanel;
    DBGrid1: TDBGrid;
    DataSource1: TDataSource;
  private
  protected
    function GetSqlClause : string; virtual; abstract;
  public
    constructor Create(AOwner: TComponent);
    { Public declarations }
  end;

implementation

{$R *.dfm}

constructor TframeMyBase.Create(AOwner: TComponent);
var
  aConnection: IMyConnection;
begin
  inherited;
  aConnection := GlobalContainer.Resolve<IMyConnection>('connection', []);
  DataSource1.DataSet := aConnection.GetQuery(GetSqlClause);
end;

end.
Burada görüleceği üzere GetSqlClause adlı bir abstract fonksiyon tanımlandı. Bundan amaç buna burada bir değer vermeyeceğiz ancak bundan türetilen Frame'ler bu fonksiyonu ezerek değer atamak zorunda kalacaklardır. Bu şekilde sonuç View.Inventories ya da View.Customers gibi birimlerimizin her biri için ayrı ayrı hep aynı işlemleri yapmaktan kurtulmuş olacağız. Ayrıca Create yapılandırıcısını her biri için yazmamız da gerekmeyecek.

Şimdi ikinci aşama olarak File/New/Other/Inheritable Items/frameMyBase seçeceğiz ve yaptığımız bu Base frame'den yeni View'larımızı türeteceğiz. 
İlkini View.Inventories.pas adıyla save edelim ve frame adına frameInventories yazalım. Burada gördüğümüz gibi bu frame için Panel, DBGrid ve DataSource hazır geldi zaten karşımıza.
Bunda protected kısmında GetSqlClause fonksiyonunu yazmamız gerekiyor onu da şöyle yapalım:
unit View.Inventories;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, View.MyBaseFrame, Data.DB, Vcl.Grids,
  Vcl.DBGrids, Vcl.ExtCtrls;

type
  TframeInventories = class(TframeMyBase)
  private
    { Private declarations }
  protected
    function GetSqlClause : string; override;
  public
    { Public declarations }
  end;

var
  frameInventories: TframeInventories;

implementation

{$R *.dfm}

{ TframeInventories }

function TframeInventories.GetSqlClause: string;
begin
  Result := 'select * from InventoryItem order by InventoryItemId';
end;

end.
View.MyBaseFrame'den bir frame daha inherit edelim ve bunu da View.Customers olarak kaydedelim, frame adını frameCustomers yapalım. F9'a bastığımızda aynen çalışacaktır. Çünkü bunlar için diğer bağlantı kodlarını oluşturmuştuk.

Şimdi, daha önce oluşturmadığımız tedarikçiler ekranını ekleyelim projeye. Bu şekilde yeni bir view eklediğimizde ne yapmamız gerektiğini de gözden geçirmiş olalım.
İlk olarak biraz yukarıda anlatıldığı gibi, File/New/Other/Inheritable Items/frameMyBase seçerek türetilmiş frame'i oluşturalım. Bunu View.Suppliers.pas adıyla kaydedelim, frame'i frameSuppliers olarak adlandıralım ve
unit View.Suppliers;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, View.MyBaseFrame, Data.DB, Vcl.Grids,
  Vcl.DBGrids, Vcl.ExtCtrls;

type
  TframeSuppliers = class(TframeMyBase)
  private
    { Private declarations }
  protected
    function GetSqlClause : string; override;
  public
    { Public declarations }
  end;

var
  frameSuppliers: TframeSuppliers;

implementation

{$R *.dfm}

{ TframeSuppliers }

function TframeSuppliers.GetSqlClause: string;
begin
  Result := 'select * from Supplier order by SupplierId';
end;

end.
Daha sonra bunu konteyner'le bağlantısını kurmak üzere uSuppliersDisplayer.pas'ı oluşturalım

unit uSuppliersDisplayer;

interface
uses System.Classes, uInterfaces, Vcl.Controls, Vcl.ExtCtrls, View.Suppliers;

type
  TInventoriesDisplayer = class(TInterfacedObject, IDisplayOnPanel)
  public
    procedure DisplayOnPanel(const aPanel: TPanel);
  end;

implementation

{ TSuppliersDisplayer }

procedure TInventoriesDisplayer.DisplayOnPanel(const aPanel: TPanel);
var frm : TframeSuppliers;
begin
  frm := TframeSuppliers.Create(aPanel);
  frm.Parent := aPanel;
  frm.Align := alClient;
end;

end.

Üçüncü olarak uRegistration.pas'a bunu ekleyeceğiz.

unit uRegistration;

interface

uses
  Spring.Container, uInterfaces;

procedure RegisterInterfaces(aMyConnection : IMyConnection);

implementation
uses
      uInventoriesDisplayer
    , uCustomersDisplayer
    , uSuppliersDisplayer
    ;

procedure RegisterInterfaces(aMyConnection : IMyConnection);
begin
  GlobalContainer.RegisterType<IDisplayOnPanel, TInventoriesDisplayer>('inventories');
  GlobalContainer.RegisterType<IDisplayOnPanel, TCustomersDisplayer>('customers');
  GlobalContainer.RegisterType<IDisplayOnPanel, TSuppliersDisplayer>('suppliers');


  GlobalContainer.RegisterInstance<IMyConnection>(aMyConnection, 'connection');

  GlobalContainer.Build;
end;

end.
ve son olarak da, MainForm'da Tedarikçiler düğmesinin OnClick event'ini yazacağız.
procedure TMainForm.btnTedarikcilerClick(Sender: TObject);
begin
  ViewClientFrame('suppliers');
end;
Evet, her yeni view eklemede ne yapacağımızı standardize etmiş olduk artık. 
Şimdi sırada bunu daha da iyileştirebilir miyiz onun araştırması olacak! Ve ardından bu view'lara bağlı olarak insert-update-delete-view detail ekranlarının sisteme entegre edilmesi söz konusu edilecek.

Projenin bu şeklini şu linkten elde edebilirsiniz : DITest-3





Hiç yorum yok:

Yorum Gönder