我正在试图找出对一些遗留代码使用依赖注入的最佳方法,这将需要很长时间才能重构并且必须逐步完成.大多数旧类使用"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) 当FreeOnTerminate = True时,为TThread后代编写Delphi DUnit测试的最佳方法是什么?TThread后代返回一个我需要测试的引用,但我无法弄清楚如何等待线程在测试中完成...
unit uThreadTests;
interface
uses
Classes, TestFramework;
type
TMyThread = class(TThread)
strict private
FId: Integer;
protected
procedure Execute; override;
public
constructor Create(AId: Integer);
property Id: Integer read FId;
end;
TestTMyThread = class(TTestCase)
strict private
FMyId: Integer;
procedure OnThreadTerminate(Sender: TObject);
protected
procedure SetUp; override;
procedure TearDown; override;
published
procedure TestMyThread;
end;
implementation
{ TMyThread }
constructor TMyThread.Create(AId: Integer);
begin
FreeOnTerminate := True;
FId := AId;
inherited Create(False);
end;
procedure TMyThread.Execute;
begin
inherited;
FId := FId + 1;
end; …
Run Code Online (Sandbox Code Playgroud) 我意识到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读取以下XML ,因为它包含无效的°符号:
V1: <Item Id="1" Description="90° Hinge"/>
Run Code Online (Sandbox Code Playgroud)
似乎Delphi 不承认在XML中执行此操作的"标准"方式:
V2: <Item Id="1" Description="90° Hinge"/>
Run Code Online (Sandbox Code Playgroud)
德尔福似乎确实处理了这个问题:
V3: <Item Id="1" Description="90° Hinge"/>
Run Code Online (Sandbox Code Playgroud)
由于我从RESTful Web服务获取数据,因此我无法控制所遇到的XML数据包,我只需要能够读取它们.
问题
使用Delphi 2010.任何帮助将不胜感激.
这似乎是一个非常愚蠢的问题,但我不知道为什么甚至允许编译:
program ConstructorWithParam;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
TThing = class(TObject)
private
FParent: TObject;
public
constructor Create(const AParent: TObject);
end;
{ TThing }
constructor TThing.Create; // <- WTF? Why does the compiler not complain?
begin
FParent := AParent;
end;
var
Thing: TThing;
begin
try
Thing := TThing.Create(TObject.Create);
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Run Code Online (Sandbox Code Playgroud)
我正在使用Delphi XE5并且没有在其他版本上测试过.谢谢.
是否可以检查具有接口类型约束的泛型类型实例的RTTI信息?问题可能有点模糊,所以我创建了一个示例控制台应用程序来显示我正在尝试做的事情:
program Project3;
{$APPTYPE CONSOLE}
uses
RTTI,
SysUtils,
TypInfo;
type
TMyAttribute = class(TCustomAttribute)
strict private
FName: string;
public
constructor Create(AName: string);
property Name: string read FName;
end;
IMyObjectBase = interface
['{E063AD44-B7F1-443C-B9FE-AEB7395B39DE}']
procedure DoSomething;
end;
TMyObjectBase = class(TInterfacedObject, IMyObjectBase)
public
procedure DoSomething; virtual;
end;
[TMyAttribute('First')]
TMyFirstRealClass = class(TMyObjectBase)
public
procedure DoSomethingDifferent;
end;
[TMyAttribute('Second')]
TMySecondRealClass = class(TMyObjectBase)
public
procedure BeSomethingDifferent;
end;
TGenericClass<I: IMyObjectBase> = class
public
function GetAttributeName(AObject: I): string;
end;
{ TMyAttribute }
constructor TMyAttribute.Create(AName: string);
begin
FName := AName;
end; …
Run Code Online (Sandbox Code Playgroud) 我想创建一个TObjectList<T>
后代来处理我的应用程序中的对象列表之间的常见功能.然后我想进一步从新类继续下载,以便在需要时引入其他功能.我似乎无法使用超过1级的继承.我可能需要更多地了解泛型,但是我搜索高低都是正确的方法来做到这一点而没有成功.到目前为止,这是我的代码:
unit edGenerics;
interface
uses
Generics.Collections;
type
TObjectBase = class
public
procedure SomeBaseFunction;
end;
TObjectBaseList<T: TObjectBase> = class(TObjectList<T>)
public
procedure SomeOtherBaseFunction;
end;
TIndexedObject = class(TObjectBase)
protected
FIndex: Integer;
public
property Index: Integer read FIndex write FIndex;
end;
TIndexedObjectList<T: TIndexedObject> = class(TObjectBaseList<T>)
private
function GetNextAutoIndex: Integer;
public
function Add(AObject: T): Integer;
function ItemByIndex(AIndex: Integer): T;
procedure Insert(AIndex: Integer; AObject: T);
end;
TCatalogueItem = class(TIndexedObject)
private
FID: integer;
public
property ID: integer read FId write FId;
end;
TCatalogueItemList = class(TIndexedObjectList<TCatalogueItem>) …
Run Code Online (Sandbox Code Playgroud) 使用Delphi Spring框架,是否可以使用GlobalContainter注册泛型类型?我正在尝试做这样的事情:
TMyBaseType = class
protected
FName: string;
function GetName: string; virtual;
procedure SetName(Value: string); virtual;
public
property Name: string read GetName write SetName;
end;
TMyFirstThing = class(TMyBaseType)
protected
function GetName: string; override;
end;
TMySecondThing = class(TMyBaseType)
protected
procedure SetName(Value: string); override;
end;
TMyGenericType<T: TMyBaseType> = class
public
procedure DoSomethingWithIt(AObject: T);
function GetTheSomethingsName(AObject: T): string;
end;
// I now want to be able to use the ServiceLocator to get me an instance
// such as TMyGenericType<TMyFirstThing> or TMyGenericType<TMySecondThing>
// but …
Run Code Online (Sandbox Code Playgroud) 我正在尝试实现 Spring 4 Delphi,并且只对接口而不是类进行编程。然而,当您想使用 TObjectList 时,这似乎是不可能的。
考虑以下代码:
unit Unit1;
interface
uses
Spring.Collections,
Spring.Collections.Lists;
type
IMyObjParent = interface
['{E063AD44-B7F1-443C-B9FE-AEB7395B39DE}']
procedure ParentDoSomething;
end;
IMyObjChild = interface(IMyObjParent)
['{E063AD44-B7F1-443C-B9FE-AEB7395B39DE}']
procedure ChildDoSomething;
end;
implementation
type
TMyObjChild = class(TInterfacedObject, IMyObjChild)
protected
procedure ParentDoSomething;
public
procedure ChildDoSomething;
end;
{ TMyObj }
procedure TMyObjChild.ChildDoSomething;
begin
end;
procedure TMyObjChild.ParentDoSomething;
begin
end;
procedure TestIt;
var
LMyList: IList<IMyObjChild>;
begin
TCollections.CreateObjectList<IMyObjChild>;
//[DCC Error] Unit1.pas(53): E2511 Type parameter 'T' must be a class type
end;
end.
Run Code Online (Sandbox Code Playgroud)
我知道我可以在上面的示例中将 IMyObjChild 更改为 TMyObjChild,但如果我在另一个单元或表单中需要它,那么我该怎么做?
当您需要 TObjectList 时,尝试仅对接口进行编程似乎太困难或不可能。 …
我正在尝试使用RTTI的通用记录,但遇到类型信息的问题.有谁知道为什么以下不能使用Delphi 2010进行编译?
program GenericTypeInfo;
{$APPTYPE CONSOLE}
uses
TypInfo,
SysUtils;
type
TMyRec<T> = record
public
Value: T;
end;
TMyInt = TMyRec<Integer>;
TMyString = TMyRec<String>;
begin
try
Writeln(GetTypeName(TypeInfo(TMyRec<Integer>))); <--- This works fine
Writeln(GetTypeName(TypeInfo(TMyRec<String>))); <--- so does this
Writeln(GetTypeName(TypeInfo(TMyInt))); <--- BUT this won't compile
Writeln(GetTypeName(TypeInfo(TMyString))); <--- nor this!!
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
Run Code Online (Sandbox Code Playgroud)
上面指出的行会生成以下编译器错误:
[DCC Error] GenericTypeInfo.dpr(24): E2134 Type 'TMyInt' has no type info
[DCC Error] GenericTypeInfo.dpr(24): E2134 Type 'TMyString' has no type info
Run Code Online (Sandbox Code Playgroud)
我不能说2之间的最大区别是什么?我承认我不是一个低级别的专家,但为什么编译器会以不同的方式对待它?我需要它来为TMyInt和TMyString类型工作.
谢谢你的帮助.
使用Spring框架中的Nullable类型设置Delphi DSharp模拟的最佳方法是什么?我尝试了各种方法,我知道我可能遗漏了一些非常简陋的东西,但我无法弄清楚如何让以下代码工作:
program DSharkMockNullable;
{$APPTYPE CONSOLE}
{$R *.res}
uses
DSharp.Testing.Mock,
Spring,
System.SysUtils;
type
{$M+}
IBaseMock = interface
['{B3311345-3C1F-47E3-8235-57B1BA04E957}']
function GetId: TNullableInteger;
procedure SetId(Value: TNullableInteger);
property Id: TNullableInteger read GetId write SetId;
end;
{$M+}
IMockMe = interface(IBaseMock)
['{07F8F233-E8F5-4743-88C5-97A66BB01E29}']
function GetObjectId: TNullableInteger;
procedure SetObjectId(Value: TNullableInteger);
property ObjectId: TNullableInteger read GetObjectId write SetObjectId;
function GetObjectName: TNullableString;
procedure SetObjectName(Value: TNullableString);
property ObjectName: TNullableString read GetObjectName write SetObjectName;
end;
TMyObject = class
public
function ObjectIdAsString(const AObject: IMockMe): string;
end;
{ TMyObject }
function TMyObject.ObjectIdAsString(const AObject: …
Run Code Online (Sandbox Code Playgroud) Spring4D库有加密类,但我无法按预期工作.我可能错误地使用它们,但是缺少任何示例都会让它变得困难.
例如,在网站https://quickhash.com/hash-sha256-online上,我可以散列单词"test"来生成以下哈希:
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Run Code Online (Sandbox Code Playgroud)
使用Spring4D库,以下代码生成不同的哈希:
CreateSHA256.ComputeHash('test').ToString;
Run Code Online (Sandbox Code Playgroud)
结果是:
9EFEA1AEAC9EDA04A892885A65FDAE0E6D9BE8C9FC96DA76D31B929262E12B1D
Run Code Online (Sandbox Code Playgroud)
抛开大/小写,它完全是一个不同的哈希.我知道一定是做错了,但是再没有使用的例子,所以我一直坚持如何做到这一点.
delphi ×12
spring4d ×6
delphi-2010 ×5
generics ×5
interface ×2
rtti ×2
cryptography ×1
delphi-xe5 ×1
dunit ×1
hash ×1
mocking ×1
tthread ×1
typeinfo ×1
unit-testing ×1
xml ×1