Reputation: 373
I have a framework that I developed with several classes and components. I would like to create a main object with access to the entire framework so that all developers can access the methods from a single location.
Example:
MyApp.Framework.DataBase
MyApp.Framework.DateUtils
MyApp.Framework.Users
MyApp.Framework.System
The object MyApp
maps entire framework and all developers have full access at any time.
The main question is to create a structure that is robust and easy to expand. After a while I would include a structure of functions and methods of the products of our company.
Example:
MyApp.Blog. (functions about Blog product)
MyApp.WebDocs. (functions WebDocs product)
More example about class:
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;
Using this class:
var
LMyApp: TMyAppBase
begin
ShowMessage(LMyApp.Users.ActiveUserName);
end;
Would that be friends, I would like if possible ideas from yours. My intention its create a single and expansive structure.
Upvotes: 1
Views: 464
Reputation: 3234
As I've already wrote in my comment, I think in this case it is a good idea to use one main Service (main class, singleton) wich can provide you access to other services. All your modules have unique ID (TGUID
). At the beginning of program execution they should register themselves in main service.
for example. main service unit:
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;
here class constructor
& destructor
simply creates and frees FServices
Dictionary. QueryService
method returns Service by its unique ID:
class function TAppServices.QueryService(ServiceID: TGUID): TCustomAppService;
begin
result := nil;
if FServices.ContainsKey(ServiceID) then
result := FServices[ServiceID];
end;
Method RegisterService
extracts RTTI
Attribute (ServciceIDAttribute
) from parameter's class name and adds this pair (id-service) to dictionary:
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;
now, about end-services. For example UserManager unit:
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.
now we can test our code:
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;
summary:
TAppServices
is the main object, wich provides access to any service in App. It knows nothing about end-services, so it has no dependencies. you can change its implementation as you wish.
You may have as many TCustomAppService class descendants as you need. When you add new service to application, you shouldn't change TAppServices
class interface or implementation.
Upvotes: 2
Reputation: 14883
You don't have to create a class for this.
Just create a unit named MyApp.Framework.DataBase
and so on. Delphi supports dots in units which makes it possible to create "namespaces".
Delphi even auto completes when you start typing Myapp.
in a uses list.
In addition you can create a class TDataBase
with static methods that you can call with TDataBase.Method
to organize simple functions/procedures in a common scope.
Upvotes: 2