1

我有一个使用多个类和组件开发的框架。我想创建一个可以访问整个框架的主对象,以便所有开发人员都可以从一个位置访问这些方法。

例子:

MyApp.Framework.DataBase
MyApp.Framework.DateUtils
MyApp.Framework.Users
MyApp.Framework.System

该对象MyApp映射整个框架,所有开发人员随时都可以完全访问。

主要问题是创建一个健壮且易于扩展的结构。过一会儿我会介绍我们公司产品的功能结构和方法。

例子:

MyApp.Blog.    (functions about Blog product)
MyApp.WebDocs. (functions WebDocs product)

关于类的更多示例:

TMyAppBase = Class
Private
  Function GetDatabase: TDataBaseClass;
  Function GetUsers: TSystemUsersClass;
  Function GetForms: TFormManager;
Public
  Constructor Create; Virtual;
  Destructor Destroy; Override;
  Property Database: TDataBaseClass Read GetDatabase;
  Property Users: TSystemUsersClass Read GetUsuarios;
  Property Forms: TFormManager Read GetForms;
End;

使用这个类:

var
  LMyApp: TMyAppBase 

begin
  ShowMessage(LMyApp.Users.ActiveUserName);
end;

那会是朋友吗,如果可能的话,我想从你那里得到想法。我的意图是创建一个单一且广泛的结构。

4

2 回答 2

2

您不必为此创建一个类。

只需创建一个命名的单元MyApp.Framework.DataBase等等。Delphi 支持单位中的点,这使得创建“命名空间”成为可能。

Myapp.当您开始输入使用列表时,Delphi 甚至会自动完成。

此外,您可以创建一个TDataBase具有静态方法的类,您可以调用该类TDataBase.Method来在公共范围内组织简单的函数/过程。

于 2012-11-21T14:43:30.283 回答
2

正如我已经在评论中写的那样,我认为在这种情况下,使用一个主要服务(主类,单例)是一个好主意,它可以让您访问其他服务。您的所有模块都有唯一的 ID ( TGUID)。在程序执行开始时,他们应该在主服务中注册自己。
例如。主要服务单位:

unit AppServices;

interface
uses generics.collections, rtti;
type
    // Unique ID Attribute for services
    ServiceIDAttribute = class(TCustomAttribute)
      strict private
        FId : TGUID;
      public
        constructor Create(ServiceID: string);
        property ID : TGUID read FId;
    end;

    //Services Base class
    TCustomAppService = class(TObject)
      strict protected
      public
    end;

    // Main Service Object
    TAppServices = class(TObject)
      strict private
       class var
        FServices : TObjectDictionary<TGUID, TCustomAppService>;
       var
      public
        class constructor Create();
        class destructor Destroy();
        class procedure RegisterService(aService : TCustomAppService);
        class function QueryService(ServiceID : TGUID):TCustomAppService;
    end;

这里class constructor&destructor简单地创建和释放 FServices字典。QueryService方法通过其唯一 ID 返回 Service:

class function TAppServices.QueryService(ServiceID: TGUID): TCustomAppService;
begin
    result := nil;
    if FServices.ContainsKey(ServiceID) then
        result := FServices[ServiceID];
end;

方法从参数的类名RegisterService中提取RTTIAttribute ( ServciceIDAttribute) 并将这一对 (id-service) 添加到字典中:

class procedure TAppServices.RegisterService(aService: TCustomAppService);
var ctx : TRttiContext;
    st : TRttiType;
    a : TCustomAttribute;
    id : TGUID;
begin
    ctx := TRttiContext.Create();
    try
        st := ctx.GetType(aService.ClassType);
        for a in st.GetAttributes() do begin
            if not (a is ServiceIDAttribute) then
                continue;
            id := ServiceIDAttribute(a).ID;

            FServices.AddOrSetValue(id, aService);
            break;
        end;
    finally
        ctx.Free();
    end;
end;

现在,关于终端服务。例如 UserManager 单元:

unit UserManager;

interface
uses AppServices;

const
    SID_UserManager : TGUID = '{D94C9E3A-E645-4749-AB15-02631F21EC4E}';
type
    [ServiceID('{D94C9E3A-E645-4749-AB15-02631F21EC4E}')]
    TUserManager = class(TCustomAppService)
      strict private
        FActiveUserName: string;
      public
        property ActiveUserName: string read FActiveUserName;
    end;


implementation


initialization
    TAppServices.RegisterService(TUserManager.Create());
end.

现在我们可以测试我们的代码:

procedure TestApp();
var uMgr :TUserManager;
    dbMgr : TDBmanager;
begin
    dbMgr := TAppServices.QueryService(SID_DBManager) as TDBManager;
    if dbMgr.Connected then
         writeln('connected!')
    else writeln('not connected');

    uMgr := TAppServices.QueryService(SID_UserManager) as TUserManager;
    writeln('Active user: ', uMgr.ActiveUserName);
end;

摘要:
TAppServices是主要对象,提供对 App 中任何服务的访问。它对终端服务一无所知,因此它没有依赖关系。您可以根据需要更改其实现。您可以根据需要拥有尽可能多的 TCustomAppService 类后代。向应用程序添加新服务时,不应更改TAppServices类接口或实现。

于 2012-11-21T20:09:12.640 回答