我想创建具有某些功能(包括搜索功能)的通用记录。为了执行此搜索,我想传递一个自定义的比较器来比较项目。如果它是一个类,我可以在构造函数中传递它,但是我想使用一条记录来避免创建或释放它。因此,我没有在哪里初始化比较器的构造函数。
然后,我决定像类型参数一样传递Comparer类,并在需要比较器时,使用TComparer.Default创建比较器的实例。
好吧,这是代码:
TMyArray<T,C: TComparer<T>> = record
FComparer: IComparer<T>;
Items: TArray<T>;
function Contains<AItem: T>: Boolean;
end;
Run Code Online (Sandbox Code Playgroud)
当我尝试以这种方式使用它时,出现问题:
TMyRecord = record
Score: Real;
A: string;
B: string;
end;
TMyRecordComparer = class(TComparer<TMyRecord>)
function Compare(Left, Right: TMyRecord): Integer;
end;
TMyRecordArray = TMyArray<TMyRecord, TMyRecordComparer>;
Run Code Online (Sandbox Code Playgroud)
有了最后一个声明,我得到以下错误:E2515类型参数'T'与类型'System.Generics.Defaults.TComparer \'不兼容。
任何想法如何解决这个问题?
我有一个 Delphi Firemonkey EXIF 实现,我在例程中使用它来加载图像文件。我试图确定图像是否已旋转,以便我可以在显示图像之前纠正图像的方向。该例程部分调用执行 BSWAP 的汇编代码来确定图像文件中标头信息的位置。这是代码的一部分:
type
TMarker = packed record
Marker : Word; //Section marker
Len : Word; //Length Section
Indefin : Array [0..4] of Char; //Indefiner - "Exif" 00, "JFIF" 00 and ets
Pad : Char; //0x00
end;
TIFDHeader = packed record
pad : Byte; //00h
ByteOrder : Word; //II (4D4D) or MM
i42 : Word; //2A00 (magic number from the 'Hitchhikers Guide'
Offset : Cardinal; //0th offset IFD
Count : Word; // number of IFD entries …Run Code Online (Sandbox Code Playgroud) 我在我的图书馆使用方法挂钩/绕行.
由于WriteProcessMemory/ReadProcessMemory是Windows API函数,因此OS X上方法挂钩/绕行的解决方案是什么?
编辑:
好吧,让我在这里提供更多信息,以便更清楚我为什么要问这个问题:
在我的DSharp库的即将推出的功能中,我有以下代码:
procedure FreeInstance(Self: TObject);
begin
...
Self.CleanupInstance;
FreeMem(Pointer(Self));
end;
var
FreeInstanceBackup: TXRedirCode;
initialization
...
HookCode(@TObject.FreeInstance, @FreeInstance, FreeInstanceBackup);
finalization
UnhookCode(@TObject.FreeInstance, FreeInstanceBackup);
...
end.
Run Code Online (Sandbox Code Playgroud)
事实是,我需要挂钩到TObject.FreeInstance方法以获得每个对象销毁的通知(是的,我知道,如果有人决定覆盖它并且不调用继承,则可能不会调用它).
另一个使用WriteProcessMemory的单元是ReturnTypePatch.pas,它修复了QC#98687,这对于像我这样的模拟库和来自Vincent Parrett的Delphi Mocks来说是不必要的(他们基本上有一个用户在我们都知道这个问题之前报告了这个问题).
WriteProcessMemory的另一个用途是在DSharp的AOP部分中,我基本上用从RTTI的TVirtualMethodInterceptor类创建的代理类VMT替换类的VMT.使用TVirtualMethodInterceptor,您只能代理现有对象 - 我的实现对整个类执行此操作(因此所有现有和将来的对象,即使是继承的).
在所有情况下,使用Move都无法写入内存,因为它们受到保护(在通过调用CopyMemory替换WriteProcessMemory时获取AV).
希望这是关于我正在使用这些功能的足够信息 - 有人可以指出我将在OS X上工作的解决方案(不幸的是我没有,所以我无法测试任何东西).
使用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) 我有一个问题应该是微不足道的,但我找不到任何优雅的答案.
我有一个a的实例,IList<string>我想得到一个逗号分隔的字符串,其中包含所有不同的(不区分大小写)值.
我以为我只是使用string.Join帮助器,因为它有一个很好的重载接受一个IEnumerator<string>as参数.不幸的是,我看到了一个障碍:spring4d重新定义IEnumerator<T>,当然,到处都使用自己的类型.
结果是以下代码无法编译:
var
distinct: system.IEnumerator<string>;
begin
result := inherited GetToken;
if assigned(result) then
begin
if not Modules.Contains(STR_DID_SESSION_MODULE) then
Modules.Add(STR_DID_SESSION_MODULE);
distinct := TDistinctIterator<string>.Create(Modules, TIStringComparer.Ordinal);
result.CustomClaims.Items[STR_CLAIM_CUSTOM_MODULES] := string.Join(',', distinct);
end;
end;
Run Code Online (Sandbox Code Playgroud)
分配distinct失败E2010 Incompatible types: 'System.IEnumerator<System.string>' and 'Spring.Collections.Extensions.TDistinctIterator<System.string>'
或者,如果我从distinct中删除命名空间,那么对它的调用将string.Join失败.
知道我应该怎么做吗?没有手动遍历迭代并手动执行连接?
注意:请耐心等待,由于此处和此处的一些讨论以及我在此处和此处报告的一些问题,我感到有点“火爆”。
一些背景
Ye olde(10.4 之前)FreeAndNil看起来像这样:
FreeAndNil(var SomeObject)
Run Code Online (Sandbox Code Playgroud)
新的和新鲜的FreeAndNil看起来是这样的:
FreeAndNil(const [ref] SomeObject: TObject);
Run Code Online (Sandbox Code Playgroud)
IMO 都有其缺点:
FreeAndNil指针、记录和接口编译得很好,但在运行时会产生有趣但通常不需要的效果。(完全狂暴,或者如果幸运的话它会因 EAccessViolation、EInvalidOperation 等而停止。)FreeAndNil像这样调用新的:FreeAndNil(TObject.Create)它会编译甚至运行得很好。我喜欢FreeAndNil在我出错时警告我并提供例如属性而不是字段的旧版本。不确定如果为此FreeAndNil实现提供对象类型属性会发生什么。没试。如果我们将签名更改为 ,FreeAndNil(var SomeObject:TObject)那么它将不允许我们传递任何其他变量类型,然后正是该TObject类型。这也是有道理的,好像不是这样FreeAndNil,人们可以轻松地更改TComponent在例程中作为类型提供的变量,将 var 变量更改为完全不同类型的对象,例如TCollection. 当然FreeAndNil不会做这样的事情,因为它总是将 var 参数更改为 nil。
所以这是FreeAndNil一个特例。
甚至可能特别到足以说服 delphi 添加一个编译器魔术 FreeAndNil实现?投票给任何人?
潜在的解决方法 …
delphi memory-management object-lifetime rad-studio delphi-run-time-library
我们可以使用以下代码获取类方法地址:
type
TMyClass = class
procedure A;
end;
var P: Pointer;
begin
P := @TMyClass.A;
end;
Run Code Online (Sandbox Code Playgroud)
对于泛型类,如何从泛型类获取方法地址?
type
TGeneric<T> = class
procedure A;
end;
var P: Pointer;
begin
P := @TGeneric<T>.A; // <--- compilation error
end.
Run Code Online (Sandbox Code Playgroud) 我在寻找一种方式来轻松和简洁地写为Delphi下DUnitX测试框架间谍.
在过去,我使用非常难看的方式:
[TestFixture]
Test = class(TObject)
public
[test]
procedure Test1;
end;
TMyClass = class(TObject)
protected
procedure MyProcedure; virtual;
end;
TMyTestClass = class(TMyClass)
protected
fMyProcedureCalled : Boolean;
procedure MyProcedure; override;
end
procedure TMyTestClass.MyProcedure;
begin
fMyProcedureCalled := true;
inherited;
end;
procedure Test.Test1;
var aObj : TMyTestClass;
begin
TMyTestClass.Create;
Assert.IsTrue(aObj.fMyProcedureCalled);
end;
Run Code Online (Sandbox Code Playgroud)
所有这些代码都用于检查是否调用了一个过程.那太冗长了!
有没有办法写一个可以帮助我减少代码的间谍?
In delphi sydney, does setting [weak] in front of an object (not an interface) make a penalty ? Exemple :
TMyObject = class(Tobject)
Private
[weak] FOwner: TMyObject;
....
end;
Run Code Online (Sandbox Code Playgroud)
I ask because I know that internally [weak] references are stored in a list and thus it's have some drawbacks (regarding speed). As now with Sydney ARC is gone there is no need anymore to put [weak] in front of an object (as far as I know), but as I want …
我通过了TObject.我知道这个对象来自TBaseClass.我想要做的是显示每个班级的所有已发布属性,直到TBaseClass.可能有更好的方法来做到这一点,但我正在尝试的是:
lObj := aObject;
while lObj.ClassType <> TBaseClass do
begin
lRttiType := lRttiContext.GetType(aObject.ClassType);
lProps := lRttiType.GetDeclaredProperties;
lStartIdx := Length(lAllProps);
SetLength(lAllProps, Length(lAllProps) + Length(lProps));
for I := Low(lProps) to High(lProps) do
lAllProps[lStartIdx + I] := lProps[I];
lObj := lObj as lObj.ClassParent;
// lObj := lObj.ClassParent.InitInstance(lObj); // *see below
end;
Run Code Online (Sandbox Code Playgroud)
这段代码的问题在于lObj.ClassType之后不会改变lObj as lObj.ClassParent.有人可以解释为什么这不起作用并提供一些有用的东西吗?
*这似乎有效,因为它将lObj.ClassType作为父类,但它会导致问题,我后来阅读文档,发现它甚至不应该首先被调用.
一直在努力解决这个问题,似乎无法找到解决方法.我使用的是Delphi XE-2.
我需要为给定包中的所有类生成私有/受保护方法的Rtti Info.
默认情况下,Delphi似乎只为公共和已发布的方法生成Rtti.
如果我将以下指令添加到包含类的Unit,则为私有和受保护字段生成Rtti,但仅为该类生成.
{$RTTI METHODS([vcPublic, vcProtected, vcPrivate])}
Run Code Online (Sandbox Code Playgroud)
我不想将此指令添加到每个单元.
我将指令添加到Packages .dpk文件中,但它没有任何效果.
谢谢!
我没有看到任何语法错误,我的代码编译干净没有完成部分.这是该单元的最后几行.
function boolAsTF(b:boolean): string; inline;
begin
if b then result := 'T' else result := 'F';
end;
finalization
SyncMgr.Free;
end.
Run Code Online (Sandbox Code Playgroud) delphi ×12
generics ×3
delphi-xe2 ×2
rtti ×2
spring4d ×2
assembly ×1
casting ×1
delphi-2010 ×1
dunit ×1
dunitx ×1
firemonkey ×1
hook ×1
macos ×1
rad-studio ×1
spy ×1
unit-testing ×1
x86-64 ×1