My question is related to the one that I wrote in the last issue ("Problems with converting Java code to delphi") that I still have problems with. Java code seen in my last question is a part of my factory class that I am trying to convert to Delphi. The problem is that I have a main interface called IStandardDataProvider
which contains common methods for the different classes in my factory. but since some of the classes also contains other methods that are not common to all of them. I use another interface that inherits from the interface IStandardDataProvider
. The problem is that I can not get the generic to work? see my whole factory class in java. How will this look like in Delphi?
我的问题与我在上一期(“将Java代码转换为delphi的问题”)中所写的问题有关,我仍然遇到问题。在我上一个问题中看到的Java代码是我工厂类的一部分,我试图转换为Delphi。问题是我有一个名为IStandardDataProvider的主界面,它包含我工厂中不同类的常用方法。但由于某些类还包含其他所有方法都不常见的方法。我使用另一个继承自IStandardDataProvider接口的接口。问题是我不能让通用工作吗?在java中看到我的整个工厂类。这在德尔福看起来如何?
public class Factory {
private static HashMap<String, IStandardDataProvider<?>> dataproviders = null;
@SuppressWarnings("unchecked")
public <T extends IStandardDataProvider<?>> T GetDataProvider(String dataProviderName) {
if (dataproviders == null)
buildDataProviderMap();
if (dataproviders.containsKey(dataProviderName)) {
return (T) dataproviders.get(dataProviderName);
} else
return null;
}
private void buildDataProviderMap() {
// Build the database connection, that will be used in all the dataproviders
DatabaseConnectionManager dbConnection = new DatabaseConnectionManager(ConfigurationManager.getConfiguration("sqlConnectionString"));
// Instantiate the Hashmap
dataproviders = new HashMap<String, IStandardDataProvider<?>>();
// Instantiate all the dataprovider implementations, and put them into the hash map
dataproviders.put("EventDataProvider", new LocalEventDataProviderImpl(dbConnection));
dataproviders.put("TaskActivityDataProvider", new LocalTaskActivityDataProviderImpl(dbConnection));
}
}
Update: Okay here is my delphi version, which I try to make generic. Currently I have only access to IStandardDataProvider
.
更新:好的,这是我的delphi版本,我尝试制作通用版本。目前我只能访问IStandardDataProvider。
type
TFactory = class(TObject)
private
DataProvider: TDictionary<string, IStandardDataProvider >;
DbConnectionManager : TDatabaseConnectionManager;
DBConnection : TSQLConnection;
Configuration : TConfigurationManager;
procedure BuildDataProviderMap;
public
constructor Create;
destructor Destroy; override;
function GetDataProvider(DataProviderName: string): IStandardDataProvider;
end;
implementation
constructor TLocalDataProviderFactory.Create;
begin
inherited Create;
DbConnectionManager := TDatabaseConnectionManager.create;
end;
destructor TLocalDataProviderFactory.Destroy;
begin
inherited;
DbConnectionManager.Free;
DataProvider.Free;
end;
function TLocalDataProviderFactory.GetDataProvider(DataProviderName: string): IStandardDataProvider;
begin
if not Assigned(DataProvider) then
BuildDataProviderMap;
if DataProvider.ContainsKey(DataProviderName) then
begin
Result := DataProvider.Items[DataProviderName];
end
else
begin
Result:= nil;
end;
end;
procedure TLocalDataProviderFactory.BuildDataProviderMap;
begin
DataProvider := TDictionary<string, IStandardDataProvider>.Create;
Configuration := TConfigurationManager.Create;
DBConnection := DbConnectionManager.GetConnection(Configuration.GetConfiguration('sqlConnectionString'));
DataProvider.Add('EventDataProvider',TLocalEventDataProviderImpl.create(DBConnection) );
DataProvider.Add('TaskActivityDataProvider',TLocalTaskActivityDataProviderImpl.create(DBConnection) );
end;
end.
1 个解决方案
#1
3
As you were told in your other question, Delphi does not support wildcard generics like Java does. The closest you can get is something like this:
正如你在其他问题中被告知的那样,Delphi不支持像Java这样的通配符泛型。你能得到的最接近的是这样的:
type
IStandardDataProvider<T> = interface(IInterface)
...
end;
type
TLocalDataProviderFactory = class
private
DataProvider: TDictionary<string, IInterface>;
DbConnectionManager : TDatabaseConnectionManager;
DBConnection : TSQLConnection;
Configuration : TConfigurationManager;
procedure BuildDataProviderMap;
public
constructor Create;
destructor Destroy; override;
function GetDataProvider<T>(DataProviderName: string): IStandardDataProvider<T>;
end;
implementation
constructor TLocalDataProviderFactory.Create;
begin
inherited Create;
DbConnectionManager := TDatabaseConnectionManager.create;
end;
destructor TLocalDataProviderFactory.Destroy;
begin
inherited;
DbConnectionManager.Free;
DataProvider.Free;
end;
function TLocalDataProviderFactory.GetDataProvider<T>(DataProviderName: string): IStandardDataProvider<T>;
begin
if not Assigned(DataProvider) then
BuildDataProviderMap;
if DataProvider.ContainsKey(DataProviderName) then
Result := DataProvider.Items[DataProviderName] as IStandardDataProvider<T>
else
Result := nil;
end;
procedure TLocalDataProviderFactory.BuildDataProviderMap;
begin
DataProvider := TDictionary<string, IInterface>.Create;
Configuration := TConfigurationManager.Create;
DBConnection := DbConnectionManager.GetConnection(Configuration.GetConfiguration('sqlConnectionString'));
DataProvider.Add('EventDataProvider', TLocalEventDataProviderImpl.Create(DBConnection) as IInterface);
DataProvider.Add('TaskActivityDataProvider', TLocalTaskActivityDataProviderImpl.Create(DBConnection) as IInterface);
end;
end.
Which really does not help you since you would need to know the concrete class that implements IStandardDataProvider<T>
in order to even call GetDataProvider()
, eg:
这对你真的没有帮助,因为你需要知道实现IStandardDataProvider
var
Provider: IStandardDataProvider<TUpdateTest>;
Provider := Factory.GetDataProvider<TUpdateTest>('EventDataProvider');
Otherwise, forget trying to make the Factory itself support Generics, let the calling code handle it instead, eg:
否则,忘记尝试使Factory本身支持Generics,让调用代码处理它,例如:
type
IStandardDataProvider<T> = interface(IInterface)
...
end;
IEventDataProvider = interface(IStandardDataProvider <TUpdateTest>)
...
end;
type
TLocalDataProviderFactory = class
private
DataProvider: TDictionary<string, IInterface>;
DbConnectionManager : TDatabaseConnectionManager;
DBConnection : TSQLConnection;
Configuration : TConfigurationManager;
procedure BuildDataProviderMap;
public
constructor Create;
destructor Destroy; override;
function GetDataProvider(DataProviderName: string): IInterface;
end;
implementation
constructor TLocalDataProviderFactory.Create;
begin
inherited Create;
DbConnectionManager := TDatabaseConnectionManager.create;
end;
destructor TLocalDataProviderFactory.Destroy;
begin
inherited;
DbConnectionManager.Free;
DataProvider.Free;
end;
function TLocalDataProviderFactory.GetDataProvider(DataProviderName: string): IInterface;
begin
if not Assigned(DataProvider) then
BuildDataProviderMap;
if DataProvider.ContainsKey(DataProviderName) then
Result := DataProvider.Items[DataProviderName]
else
Result := nil;
end;
procedure TLocalDataProviderFactory.BuildDataProviderMap;
begin
DataProvider := TDictionary<string, IInterface>.Create;
Configuration := TConfigurationManager.Create;
DBConnection := DbConnectionManager.GetConnection(Configuration.GetConfiguration('sqlConnectionString'));
DataProvider.Add('EventDataProvider', TLocalEventDataProviderImpl.Create(DBConnection) as IInterface);
DataProvider.Add('TaskActivityDataProvider', TLocalTaskActivityDataProviderImpl.Create(DBConnection) as IInterface);
end;
end.
var
Provider: IEventDataProvider;
Provider := Factory.GetDataProvider('EventDataProvider') as IEventDataProvider;
#1
3
As you were told in your other question, Delphi does not support wildcard generics like Java does. The closest you can get is something like this:
正如你在其他问题中被告知的那样,Delphi不支持像Java这样的通配符泛型。你能得到的最接近的是这样的:
type
IStandardDataProvider<T> = interface(IInterface)
...
end;
type
TLocalDataProviderFactory = class
private
DataProvider: TDictionary<string, IInterface>;
DbConnectionManager : TDatabaseConnectionManager;
DBConnection : TSQLConnection;
Configuration : TConfigurationManager;
procedure BuildDataProviderMap;
public
constructor Create;
destructor Destroy; override;
function GetDataProvider<T>(DataProviderName: string): IStandardDataProvider<T>;
end;
implementation
constructor TLocalDataProviderFactory.Create;
begin
inherited Create;
DbConnectionManager := TDatabaseConnectionManager.create;
end;
destructor TLocalDataProviderFactory.Destroy;
begin
inherited;
DbConnectionManager.Free;
DataProvider.Free;
end;
function TLocalDataProviderFactory.GetDataProvider<T>(DataProviderName: string): IStandardDataProvider<T>;
begin
if not Assigned(DataProvider) then
BuildDataProviderMap;
if DataProvider.ContainsKey(DataProviderName) then
Result := DataProvider.Items[DataProviderName] as IStandardDataProvider<T>
else
Result := nil;
end;
procedure TLocalDataProviderFactory.BuildDataProviderMap;
begin
DataProvider := TDictionary<string, IInterface>.Create;
Configuration := TConfigurationManager.Create;
DBConnection := DbConnectionManager.GetConnection(Configuration.GetConfiguration('sqlConnectionString'));
DataProvider.Add('EventDataProvider', TLocalEventDataProviderImpl.Create(DBConnection) as IInterface);
DataProvider.Add('TaskActivityDataProvider', TLocalTaskActivityDataProviderImpl.Create(DBConnection) as IInterface);
end;
end.
Which really does not help you since you would need to know the concrete class that implements IStandardDataProvider<T>
in order to even call GetDataProvider()
, eg:
这对你真的没有帮助,因为你需要知道实现IStandardDataProvider
var
Provider: IStandardDataProvider<TUpdateTest>;
Provider := Factory.GetDataProvider<TUpdateTest>('EventDataProvider');
Otherwise, forget trying to make the Factory itself support Generics, let the calling code handle it instead, eg:
否则,忘记尝试使Factory本身支持Generics,让调用代码处理它,例如:
type
IStandardDataProvider<T> = interface(IInterface)
...
end;
IEventDataProvider = interface(IStandardDataProvider <TUpdateTest>)
...
end;
type
TLocalDataProviderFactory = class
private
DataProvider: TDictionary<string, IInterface>;
DbConnectionManager : TDatabaseConnectionManager;
DBConnection : TSQLConnection;
Configuration : TConfigurationManager;
procedure BuildDataProviderMap;
public
constructor Create;
destructor Destroy; override;
function GetDataProvider(DataProviderName: string): IInterface;
end;
implementation
constructor TLocalDataProviderFactory.Create;
begin
inherited Create;
DbConnectionManager := TDatabaseConnectionManager.create;
end;
destructor TLocalDataProviderFactory.Destroy;
begin
inherited;
DbConnectionManager.Free;
DataProvider.Free;
end;
function TLocalDataProviderFactory.GetDataProvider(DataProviderName: string): IInterface;
begin
if not Assigned(DataProvider) then
BuildDataProviderMap;
if DataProvider.ContainsKey(DataProviderName) then
Result := DataProvider.Items[DataProviderName]
else
Result := nil;
end;
procedure TLocalDataProviderFactory.BuildDataProviderMap;
begin
DataProvider := TDictionary<string, IInterface>.Create;
Configuration := TConfigurationManager.Create;
DBConnection := DbConnectionManager.GetConnection(Configuration.GetConfiguration('sqlConnectionString'));
DataProvider.Add('EventDataProvider', TLocalEventDataProviderImpl.Create(DBConnection) as IInterface);
DataProvider.Add('TaskActivityDataProvider', TLocalTaskActivityDataProviderImpl.Create(DBConnection) as IInterface);
end;
end.
var
Provider: IEventDataProvider;
Provider := Factory.GetDataProvider('EventDataProvider') as IEventDataProvider;