编码笔记

导航

通过TCustomAttribute和反射实现动态查询(二)

再实现一个基类,通过反射来解析TCustomAttribute类,组合成SQL语句。

unit uBISearchBaseClass;

interface

uses
  System.Classes, System.TypInfo, System.Rtti, System.SysUtils, uBISearchAttributeIni,
  cxGrid, uBISearchAttributes, cxGridDBTableView;

type
  /// <summary>
  /// 基本信息模糊查询的种类。
  /// </summary>
  /// <remarks>
  /// 商品、单位、职员、部门、仓库、地区。
  /// </remarks>
  TBISearchType = (bistGood, bistUnit, bistEmployee, bistDepartment, bistStore,
    bistArea);

  /// <summary>
  /// 基本信息模糊查询控制基类,实现字段配置、SQL的构造等功能。
  /// </summary>
  TBISearchBaseClass = class
  strict private
    FBISearchAttributeIniFile : TBISearchAttributeIniFile;
    FSelectSQL : string;
    FBISelectMatchType : TBISelectMatchType;
    FWheres: TStrings;
    FSelects: TStrings;
    procedure SetBISelectMatchType(const Value: TBISelectMatchType);
  protected
    procedure IniSelectSQL; virtual;
  public
    constructor Create(ABISearchType : TBISearchType); virtual;
    destructor Destroy; override;

    /// <summary>
    /// 保存查询列配置Where字段到ini文件。
    /// </summary>
    procedure SaveWhereFieldConfig(AFieldAlias : string; ASelected : Boolean); virtual;
    /// <summary>
    /// 保存查询列配置Select字段到ini文件。
    /// </summary>
    procedure SaveSelectFieldConfig(AFieldAlias : string; ASelected : Boolean); virtual;
    /// <summary>
    /// 获取查询语句。
    /// </summary>
    function SelectSQL(AFilter : string) : string;
    /// <summary>
    /// 获取指定Where字段是否被勾选,即字段是否参与where的生成。
    /// </summary>
    function WhereChecked(AFieldAlias : string) : Boolean;
    /// <summary>
    /// 获取指定Select字段是否被勾选,即字段是否参与select的生成。
    /// </summary>
    function SelectChecked(AFieldAlias : string) : Boolean;
    procedure InitDBTableView(AGrid: TcxGridDBTableView); virtual;
    property BISelectMatchType : TBISelectMatchType read FBISelectMatchType write SetBISelectMatchType;
    property Wheres : TStrings read FWheres;
    property Selects : TStrings read FSelects;
  end;

implementation

{ TBISearchBaseClass }

constructor TBISearchBaseClass.Create(ABISearchType: TBISearchType);
var
  sType : string;
begin
  FWheres := TStringList.Create;
  FSelects := TStringList.Create;

  FBISearchAttributeIniFile := TBISearchAttributeIniFile.Create(nil);
  sType := GetEnumName(TypeInfo(TBISearchType), Ord(ABISearchType));
  FBISearchAttributeIniFile.SetBISearchType(sType);
  FBISelectMatchType := smtRight;

  IniSelectSQL;
end;

destructor TBISearchBaseClass.Destroy;
begin
  FBISearchAttributeIniFile.Free;
  FWheres.Free;
  FSelects.Free;
  inherited;
end;

procedure TBISearchBaseClass.IniSelectSQL;
var
  ctx : TRttiContext;
  t : TRttiType;
  p : TRttiProperty;
  a : TCustomAttribute;

  AValid : Boolean;

  szSQL, szSelect, szWhere, szFrom, szWhereDefault : string;

  szWhereItem, szSelectItem, szSonCount : string;
begin
  szSQL := '';
  szSelect := '';
  szWhere := '';
  szWhereDefault := '';
  szSonCount := '';

  ctx := TRttiContext.Create;
  try
    t := ctx.GetType(ClassType);

    for a in t.GetAttributes do
    begin
      if a is TBaseInfoQueryMainTable then
      begin
        szFrom := TBaseInfoQueryMainTable(a).TableName;

        FBISelectMatchType := TBISelectMatchType(FBISearchAttributeIniFile.MatchType);
      end;
    end;

    for p in t.GetProperties do
      for a in p.GetAttributes do
      begin
        if a is TBaseInfoQueryWhereFieldsAttribute then
        begin
          szWhereItem := TBaseInfoQueryWhereFieldsAttribute(a).FieldCaption;
          if not FBISearchAttributeIniFile.WhereExists(TBaseInfoQueryWhereFieldsAttribute(a).FieldAlias) then
            AValid := TBaseInfoQueryWhereFieldsAttribute(a).Checked
          else
            AValid := FBISearchAttributeIniFile.WhereChecked(TBaseInfoQueryWhereFieldsAttribute(a).FieldAlias);
          (* 如果该字段是勾选有效的,则加入where语句。*)
          if AValid then
          begin
            szWhereItem := szWhereItem + '=1;'+TBaseInfoQueryWhereFieldsAttribute(a).FieldAlias;
            szWhere := szWhere + TBaseInfoQueryWhereFieldsAttribute(a).TableName+'.'+TBaseInfoQueryWhereFieldsAttribute(a).FieldName + ' like %% or ';
          end
          else
          begin
            szWhereItem := szWhereItem + '=0;'+TBaseInfoQueryWhereFieldsAttribute(a).FieldAlias;
            szWhereDefault := szWhereDefault + TBaseInfoQueryWhereFieldsAttribute(a).TableName+'.'+TBaseInfoQueryWhereFieldsAttribute(a).FieldName + ' like %% or ';
          end;
          FWheres.Add(szWhereItem);
        end;
        if a is TBaseInfoQuerySelectFieldsAttribute then
        begin
          szSelectItem := TBaseInfoQuerySelectFieldsAttribute(a).FieldCaption;
          if not FBISearchAttributeIniFile.SelectExists(TBaseInfoQuerySelectFieldsAttribute(a).FieldAlias) then
            AValid := TBaseInfoQuerySelectFieldsAttribute(a).Visible
          else          
            AValid := FBISearchAttributeIniFile.SelectChecked(TBaseInfoQuerySelectFieldsAttribute(a).FieldAlias);
          if AValid or TBaseInfoQuerySelectFieldsAttribute(a).Fixed then
          begin
            if TBaseInfoQuerySelectFieldsAttribute(a).FieldAlias <> TBaseInfoQuerySelectFieldsAttribute(a).FieldName then
            begin
              szSelect := szSelect + TBaseInfoQuerySelectFieldsAttribute(a).FieldName
                +' as '+TBaseInfoQuerySelectFieldsAttribute(a).FieldAlias+','
            end
            else
            begin
              szSelect := szSelect + TBaseInfoQuerySelectFieldsAttribute(a).FieldName+','
            end;

            if szSonCount = '' then
            begin
              if TBaseInfoQuerySelectFieldsAttribute(a).FieldCaption='儿子数' then
                szSonCount := ' and '+ TBaseInfoQuerySelectFieldsAttribute(a).FieldName+'=0';
            end;

            if AValid then
            begin
              szSelectItem := szSelectItem + '=1;'+TBaseInfoQuerySelectFieldsAttribute(a).FieldAlias
            end
            else
            begin
              (* 隐藏的固定Select字段不支持自定义。*)
              Continue;
            end;
          end
          else
          begin
            szSelectItem := szSelectItem + '=0;'+TBaseInfoQuerySelectFieldsAttribute(a).FieldAlias;
          end;
          FSelects.Add(szSelectItem);
        end;
      end;
    if szWhere = '' then
    begin
      szWhere := szWhereDefault;        
    end;
    szWhere := szWhere.Substring(0, szWhere.Length-3);
    szSelect := szSelect.TrimRight([',']);
    szSQL := 'select ' + szSelect +' from ' +szFrom + ' where ' +'('+ szWhere+')'+szSonCount;
    FSelectSQL := szSQL;
  finally
    ctx.Free;
  end;
end;

procedure TBISearchBaseClass.InitDBTableView(AGrid: TcxGridDBTableView);
var
  ctx : TRttiContext;
  t : TRttiType;
  p : TRttiProperty;
  a : TCustomAttribute;

  AValid : Boolean;
  AcxGridDBColumn : TcxGridDBColumn;  
begin
  ctx := TRttiContext.Create;
  AGrid.ClearItems;
  try
    t := ctx.GetType(ClassType);

    for p in t.GetProperties do
      for a in p.GetAttributes do
      begin  
        if a is TBaseInfoQuerySelectFieldsAttribute then
        begin
          if not FBISearchAttributeIniFile.SelectExists(TBaseInfoQuerySelectFieldsAttribute(a).FieldAlias) then
            AValid := TBaseInfoQuerySelectFieldsAttribute(a).Visible
          else          
            AValid := FBISearchAttributeIniFile.SelectChecked(TBaseInfoQuerySelectFieldsAttribute(a).FieldAlias);

          AValid := AValid or TBaseInfoQuerySelectFieldsAttribute(a).Fixed;
          if AValid then
          begin
            AcxGridDBColumn := AGrid.CreateColumn;
            AcxGridDBColumn.DataBinding.FieldName := TBaseInfoQuerySelectFieldsAttribute(a).FieldAlias;
            AcxGridDBColumn.Caption := TBaseInfoQuerySelectFieldsAttribute(a).FieldCaption;
            if TBaseInfoQuerySelectFieldsAttribute(a).Visible then
            begin
              AcxGridDBColumn.VisibleForCustomization := True;
              AcxGridDBColumn.Visible := True;
            end
            else
            begin
              AcxGridDBColumn.VisibleForCustomization := False;
              AcxGridDBColumn.Visible := False;
            end;
            AcxGridDBColumn.Tag := 0;
            if TBaseInfoQuerySelectFieldsAttribute(a).FieldCaption='ID' then
              AcxGridDBColumn.Tag := 100
            else
            if TBaseInfoQuerySelectFieldsAttribute(a).FieldCaption='fullid' then
              AcxGridDBColumn.Tag := 101
            else
            if TBaseInfoQuerySelectFieldsAttribute(a).FieldCaption='儿子数' then
              AcxGridDBColumn.Tag := 102;
          end;
        end;      
      end;
  finally

  end;
end;

procedure TBISearchBaseClass.SaveSelectFieldConfig(AFieldAlias: string;
  ASelected: Boolean);
begin
  if ASelected then
    FBISearchAttributeIniFile.CheckSelect(AFieldAlias)
  else
  begin
    FBISearchAttributeIniFile.UnCheckSelect(AFieldAlias);
  end;
end;

procedure TBISearchBaseClass.SaveWhereFieldConfig(AFieldAlias : string;
  ASelected : Boolean);
begin
  if ASelected then
    FBISearchAttributeIniFile.CheckWhere(AFieldAlias)
  else
  begin
    FBISearchAttributeIniFile.UnCheckWhere(AFieldAlias);
  end;
end;

function TBISearchBaseClass.WhereChecked(AFieldAlias: string): Boolean;
begin
  Result := FBISearchAttributeIniFile.WhereChecked(AFieldAlias);
end;

function TBISearchBaseClass.SelectChecked(AFieldAlias: string): Boolean;
begin
  Result := FBISearchAttributeIniFile.SelectChecked(AFieldAlias);
end;

function TBISearchBaseClass.SelectSQL(AFilter : string): string;
var
  szMatch : string;

  AMatchType : TBISelectMatchType;
begin
  IniSelectSQL;
  if Wheres.Count = 0 then
  begin
    Exit('');
  end;

  AMatchType := FBISelectMatchType;

  case ord(AMatchType) of
    0 : szMatch := QuotedStr('%'+Trim(AFilter));
    1 : szMatch := QuotedStr(Trim(AFilter)+'%');
    2 : szMatch := QuotedStr('%'+Trim(AFilter)+'%');
  end;
  Result := StringReplace(FSelectSQL, '%%', szMatch, [rfReplaceAll]);
end;

procedure TBISearchBaseClass.SetBISelectMatchType(
  const Value: TBISelectMatchType);
begin
  FBISelectMatchType := Value;
  FBISearchAttributeIniFile.MatchType := Ord(Value);
end;

end.

 

posted on 2013-08-05 14:20  封三郎  阅读(604)  评论(0编辑  收藏  举报