这在德尔福看起来如何?

时间:2021-10-14 21:41:09

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 的具体类才能调用GetDataProvider(),例如:

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 的具体类才能调用GetDataProvider(),例如:

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;