标签: spring4d

父属性的构造函数注入与setter注入

我正在试图找出对一些遗留代码使用依赖注入的最佳方法,这将需要很长时间才能重构并且必须逐步完成.大多数旧类使用"Parent"属性来确定各种事物,而父属性通常通过构造函数参数传递,如下所示:

constructor TParentObject.Create;
begin
  FChildObject := TChildObject.Create(Self);
end;

constructor TChildObject.Create(AParent: TParentObject)
begin
  FParent := AParent;
end;
Run Code Online (Sandbox Code Playgroud)

这是我们遗留代码库的典型代表.但是,当移动到接口和构造函数注入时,Spring4D框架在创建Child对象时不知道Parent.所以它只会得到一个新的父母而不是现有的父母.当然我可以创建一个属性getter/setter,但这表示该类的"可选"属性,它实际上是一个强制属性.有关更多说明,请参阅以下代码:

unit uInterfaces;

interface

uses
  Spring.Collections;

type

  IChildObject = interface;

  IParentObject = interface
  ['{8EA8F9A2-E627-4546-8008-0A77DA2B16F1}']
    function GetSomethingRequiredByChild: string;
    procedure SetSomethingRequiredByChild(const Value: string);
    property SomethingRequiredByChild: string read GetSomethingRequiredByChild write SetSomethingRequiredByChild;
    function GetChild: IChildObject;
    property Child: IChildObject read GetChild;
  end;

  // This introduces a property getter/setter
  // However it also implies that Parent can be NIL which it cannot
  IChildObject = interface
  ['{ECCA09A6-4A52-4BE4-A72E-2801160A9086}']
    function GetParent: IParentObject;
    procedure …
Run Code Online (Sandbox Code Playgroud)

delphi dependency-injection spring4d

13
推荐指数
1
解决办法
804
查看次数

春天4D.谁在使用这个框架,你的经历是什么?

我已经用Delphi编写了一年的代码.但是我对.NET有更多的经验.我正在阅读Nick Hodges的书"编码在Delphi中",他介绍并认可了Spring 4 Delphi框架.

我立即对基于IEnumerable的泛型集合感到兴奋.

然而,我的同事对使用该框架持保留意见.这主要是由于缺乏文档以及Delphi在此继承级别上关于泛型的稳健性/稳定性的一些不安全性.

所以问题.你有什么经历?任何问题?你在生产中使用框架吗?

我们目前仍在XE2上,但预计在未来几个月内转向XE4.

谢谢!

delphi delphi-xe2 spring4d

11
推荐指数
0
解决办法
6098
查看次数

Delphi界面助手/解决方法

我意识到Delphi不支持接口助手,但在阅读了几个SO主题和Spring4D的来源之后,我想知道有没有办法实现以下目的?源代码评论几乎总结了我正在尝试做的事情,所以这里是:

program IHelper;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Spring,
  System.SysUtils;

type

  IMyThing = interface
  ['{01E799A5-9141-4C5E-AA85-B7C9792024D9}']
    procedure BasicThing;
  end;

  TMyThing = class(TInterfacedObject, IMyThing)
  strict private
    procedure BasicThing;
  end;

  IMyThingHelper = record
  private
    FOutage: IMyThing;
  public
    class operator Implicit(const Value: IMyThing): IMyThingHelper;
    procedure HelpfulThing;
  end;

  TMyThingHelper = class helper for TMyThing
  public
    class procedure ObjectThing;
  end;

{ TOutage }

procedure TMyThing.BasicThing;
begin
  Writeln('Basic Thing');
end;


{ IOutageHelper }

procedure IMyThingHelper.HelpfulThing;
begin
  Writeln('Helpful thing');
end;

class operator IMyThingHelper.Implicit(const Value: IMyThing): IMyThingHelper;
begin
  Result.FOutage …
Run Code Online (Sandbox Code Playgroud)

delphi interface spring4d delphi-xe5

10
推荐指数
1
解决办法
2215
查看次数

当T是事件处理程序时,IList <T>崩溃了吗?

在我看来,IList不能将事件处理程序作为其元素.该程序在PROGRAM退出时具有访问冲突$ C00000005.

如果我使用Delphi RTL的TList,一切都很好.

32位和64位构建都会发生访问冲突.当它发生时,它似乎停在Spring4D的以下几行:

procedure TCollectionBase<T>.Changed(const item: T; action:      
   TCollectionChangedAction);
begin
   if fOnChanged.CanInvoke then
       fOnChanged.Invoke(Self, item, action);
end;
Run Code Online (Sandbox Code Playgroud)

以下示例程序可以在Windows上使用RAD Studio Tokyo 10.2.3复制访问冲突.

program Test_Spring_IList_With_Event_Handler;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Spring.Collections;

type
  TSomeEvent = procedure of object;

  TMyEventHandlerClass = class
    procedure SomeProcedure;
  end;

  TMyClass = class
  private
    FEventList: IList<TSomeEvent>;
  public
    constructor Create;
    destructor Destroy; override;
    procedure AddEvent(aEvent: TSomeEvent);
  end;

procedure TMyEventHandlerClass.SomeProcedure;
begin
  // Nothing to do.
end;

constructor TMyClass.Create;
begin
  inherited;
  FEventList := TCollections.CreateList<TSomeEvent>;
end;

destructor TMyClass.Destroy;
begin
  FEventList …
Run Code Online (Sandbox Code Playgroud)

delphi spring4d

10
推荐指数
1
解决办法
258
查看次数

delphi - 如何将参数从实例化器传递给spring4d依赖注入框架中的构造函数?

可以注册一个具有预期从创建点传递的参数的类吗?

我知道可以这样做:

GlobalContainer.RegisterType<TUserProcessor>.Implements<IUserUpgrader>.
AsTransient.DelegateTo(
    function: TUserProcessor
    begin
      Result := TUserProcessor.Create(GetCurrentUser);
    end
  );
Run Code Online (Sandbox Code Playgroud)

但是参数被绑定到容器被注册的执行上下文,而不是对象获取的地方.

这样的事情可能就是这样吗?

GlobalContainer.Resolve<IMathService>([FCurrentUser]);
Run Code Online (Sandbox Code Playgroud)

我知道一些peoble的拥护者拥有非常简单的构造函数,但有时候构造函数参数看起来很清楚:

  1. 构造的对象需要使用object参数,因此必须满足引用.该参数还使得该约束在类中更加明显.

  2. 你可以在方法或属性中分配引用,如果在没有先完成赋值的情况下尝试使用该对象,则可以在每个其他方法中引发和异常.我不喜欢编写这种类型的代码,这只是浪费时间,只是使用构造函数参数并检查那里.代码越少,IMO越好.

  3. 此外,对象被传递给使用容器(例如Transaction对象)构造新对象的对象本地,并且具有一些状态(它不是我可以通过容器获得的新对象).

delphi dependency-injection delphi-xe2 spring4d

8
推荐指数
1
解决办法
1544
查看次数

如何确保使用Spring Framework在我的应用程序中包含给定的依赖项?

这将是一个难以描述的问题,但是这里有.

我们正在使用Delphi Spring Framework.(http://code.google.com/p/delphi-spring-framework/)

假设我有UnitA声明由ClassA实现的InterfaceA.

类似地,我有UnitB声明由ClassB实现的InterfaceB.

两者都在其各自的初始化部分中使用Spring Container注册了它们的接口和类.

InterfaceA依赖于InterfaceB,但由于我们使用的是Spring,因此UnitA的uses子句中没有UnitB .换句话说,我们已经完成了我们的工作 - 我们已经将UnitA和UnitB分离,但我们仍然可以让InterfaceA依赖于InterfaceB.

但是,鉴于上述情况,我们需要确保UnitA和UnitB都包含在项目中,以便可以解析依赖关系.

想象一下,现在,我们开始一个新项目.该新项目使用UnitA,但开发人员没有意识到如果要使用UnitA,则还必须在项目中包含UnitB.不会出现编译器错误,因为依赖项是在运行时解决的,而不是编译时.

这就是一个问题:在应用程序部署之前,确保对UnitB的这种依赖性是否已知的正确方法是什么?

我们可以预见复杂应用程序中的情况,尽管进行了全面测试,但是可能很长时间没有执行给定的代码路径,并且在部署之前未发现此缺失的依赖关系.

我们已经实现了一个系统,其中每个接口解析调用都伴随着一个Requires调用,在启动时检查并引发异常,确保我们看到错误.但我们想知道是否有"最佳实践"或标准方法来检测此问题或以其他方式处理此问题.

补充: 这是Java和其他语言的问题吗?

java delphi dependency-injection ioc-container spring4d

7
推荐指数
2
解决办法
392
查看次数

Delphi Spring DI:是否可以在没有实现类型的情况下委托接口实例化?

我刚刚开始使用Delphi Spring Framework,并想知道当前版本的DI容器是否允许将构造委托给工厂方法而不指定实现类型?

例如类似的东西:

GlobalContainer
  .RegisterFactory<ISomeObject>(
    function: ISomeObject 
    begin 
      Result := CreateComObject(CLASS_SomeObject) as ISomeObject; 
    end)
  .Implements<ISomeObject>  // could probably be implied from the above
  .AsSingletonPerThread;
Run Code Online (Sandbox Code Playgroud)

如您所见,我的具体用例是COM对象的实例化.在这种情况下,实现我感兴趣的接口的类不是我的应用程序的一部分,但我仍然可以通过调用CreateComObject/ 来创建实例CoCreateInstance.但是,似乎我运气不好,因为Container中的注册似乎总是绑定到实际的实现类.

假设目前不可能这样做,那么你们的专家怎么解决这个问题呢?你会创建一个包装类或虚拟类,或者你只是将COM对象保留在DI容器之外并简单地通过它实例化它们CreateComObject

delphi com dependency-injection ioc-container spring4d

7
推荐指数
1
解决办法
1120
查看次数

如何安装Spring4D

我已经下载了最新版本的 Delphi Spring 框架。按照自述文件中的指示,我运行 Build.exe 并选择了两个版本的 Delphi(XE5 和 Seattle)。在 Delphi 安装中,我看不到软件包已安装,也看不到我的库搜索路径已修改。我缺少什么或者我还必须做些什么才能安装和使用它?

在此先感谢您的帮助。

delphi spring4d

7
推荐指数
1
解决办法
2104
查看次数

为什么迭代后自动释放TObjectList类型的列表?

我有一个关于Spring4D框架的TObjectList类的行为的问题.在我的代码创建的几何图形,诸如列表square,circle,triange,各自定义一个单独的类.为了在列表被破坏时自动释放几何图形,我定义了一个类型为TObjectList的列表,如下所示:

procedure TForm1.FormCreate(Sender: TObject);
var
  geometricFigures: TObjectList<TGeometricFigure>;
  geometricFigure: TGeometricFigure;
begin
  ReportMemoryLeaksOnShutdown := true;

  geometricFigures := TObjectList<TGeometricFigure>.Create();
  try
    geometricFigures.Add(TCircle.Create(4,2));
    geometricFigures.Add(TCircle.Create(0,4));
    geometricFigures.Add(TRectangle.Create(3,10,4));
    geometricFigures.Add(TSquare.Create(1,5));
    geometricFigures.Add(TTriangle.Create(5,7,4));
    geometricFigures.Add(TTriangle.Create(2,6,3));

    for geometricFigure in geometricFigures do begin
      geometricFigure.ToString();
    end;
  finally
    //geometricFigures.Free(); -> this line is not required (?)
  end;
end;
Run Code Online (Sandbox Code Playgroud)

如果我运行此代码,geometricFigures即使我没有Free在列表中调用方法,也会自动从内存中释放列表(注意在finally块中注释掉了行).我期望一个不同的行为,我认为该列表需要显式调用Free(),因为局部变量geometricFigures不使用接口类型.

我进一步注意到,如果列表中的项目没有在for-in循环中迭代(我暂时将其从代码中删除),则列表不会自动释放,并且我会收到内存泄漏.

这引出了以下问题:为什么TObjectList(geometricFigures)类型的列表在迭代其项时会自动释放,但如果从代码中删除for-in循环则不会?

更新

我按照塞巴斯蒂安的建议调试了析构函数.列表项被以下代码破坏:

{$REGION 'TList<T>.TEnumerator'}

constructor TList<T>.TEnumerator.Create(const list: TList<T>);
begin
  inherited Create;
  fList := list;
  fList._AddRef;
  fVersion := fList.fVersion;
end;

destructor TList<T>.TEnumerator.Destroy; …
Run Code Online (Sandbox Code Playgroud)

delphi spring4d

7
推荐指数
2
解决办法
1337
查看次数

如何从列表中删除所有重复项?

考虑这个测试应用:

function RemoveDuplicates(const Input: IEnumerable<Integer>): IEnumerable<Integer>;
begin
  // How to implement this function?
end;

var
  Enumerable: IEnumerable<Integer>;
  UniqueEnumerable: IEnumerable<Integer>;
begin
  Enumerable := TCollections.CreateList<Integer>([1, 1, 2, 3, 3, 3, 4]);
  UniqueEnumerable := RemoveDuplicates(Enumerable);
  UniqueEnumerable.ForEach(
    procedure(const I: Integer)
    begin
      WriteLn(I);
    end);
  ReadLn;
end.
Run Code Online (Sandbox Code Playgroud)

如何实现该RemoveDuplicates功能(这nub在Haskell中调用)?

delphi list unique spring4d delphi-xe7

6
推荐指数
1
解决办法
920
查看次数