提问人:Ravaut123 提问时间:11/17/2023 最后编辑:Remy LebeauRavaut123 更新时间:11/17/2023 访问量:89
为什么我不能从 RTTI 获得 IList 的“添加”和“清除”方法
Why can't I get the 'Add' and 'Clear' methode of IList from RTTI
问:
我有一个接口(来自 ),我想用MVCFrameWork反序列化。它不起作用,因为在代码中我们有一个函数,用于查看方法是否存在,但 RTTI 不包括这些方法。IList<T>
Spring.Collections
IsWrap()
Add()
Clear()
IList
一些代码:
TPerson = class (TInterfacedObject)
private
fLastName: String;
fFirstName: String;
public
property FirstName: String read fFirstName write fFirstName;
property LastName: String read fLastName write fLastName;
end;
implementation
uses
Generics.Collections,
Spring.Collections,
MVCFramework.Serializer.Intf,
MVCFramework.Serializer.JsonDataObjects;
procedure TSerializerTest.JsonToCollection;
begin
var strJson: string := '[{"FirstName": "Ricardo", "LastName": "The killer" }, {"FirstName": "Zorro", "LastName": "Z-Man" }]';
var oPersons : IList<TPerson> := TCollections.CreateObjectList<TPerson> ;
// var oPersons : TList<TPerson> := TList<TPerson>.Create ;
// var oPersons : TObjectList<TPerson> := TObjectList<TPerson>.Create() ;
var lSerializer: IMVCSerializer := TMVCJsonDataObjectsSerializer.Create;
lSerializer.DeserializeCollection(strJson, oPersons, TPerson);
Assert.AreEqual(oPersons[0].FirstName , 'Ricardo');
Assert.AreEqual(oPersons[1].FirstName , 'Zorro');
end;
TList<TPerson>
和工作。TObjectList<TPerson>
IList<TPerson>
不起作用,因为我们找不到方法和 RTTI。Add()
Clear()
procedure TSerializerTest.CheckAddAndClearRTTI;
var
ObjectType: TRttiType;
FContext: TRttiContext;
begin
var oPersons : IList<TPerson> := TCollections.CreateObjectList<TPerson> ;
//METHODE ADD AND CLEAR EXIST
oPersons.Add(TPerson.Create);
oPersons.Clear;
ObjectType := FContext.GetType(oPersons.AsObject.ClassInfo);
if (ObjectType.GetMethod('Add') <> nil) and (ObjectType.GetMethod('Clear') <> nil) then
begin
ShowMessage('Is List'); // DOES NOT GET HERE, WHY
end;
end;
答:
我假设您使用的是 Spring4D 2.0,因为在 1.2 中,继承的接口默认为它们提供方法 RTTI。IInvokable
但是,在 2.0 中,这种情况发生了变化,接口和支持它们的对象都不会发出任何增强的 RTTI,因为接口不再继承或添加到它们,并且在实现类中,所有增强的 RTTI 都通过子句关闭。这是设计使然,以避免导致大量不必要的二进制膨胀。IInvokable
{$M+}
$RTTI
知道在集合上使用 RTTI 的主要用途之一是序列化,Spring4D 提供了另一种方法:
列表和许多其他集合类型支持非泛型接口,从该接口内部创建围绕泛型集合的包装对象,并公开 和 和 方法的功能。ICollection
Spring.Collections
IEnumerable
Add(const value: TValue)
Clear
var persons := TCollections.CreateObjectList<TPerson>;
var coll := persons as ICollection;
coll.Add(TPerson.Create);
coll.Clear;
我快速研究了 DMVC 代码,我可以说它们处理接口的方式很糟糕,只需将它们转换为对象并将其传递下来。我不知道他们是否有一些自定义序列化的扩展点,但这需要修复。
感谢 Stefan 和 Remy。
在DMVC中,我可以进行自定义序列化
TListSerializer = class(TInterfacedObject, IMVCTypeSerializer)
public
procedure SerializeAttribute(const AElementValue: TValue; const APropertyName: string;const ASerializerObject: TObject; const AAttributes: System.TArray<System.TCustomAttribute>);
procedure SerializeRoot(const AObject: TObject; out ASerializerObject: TObject;const AAttributes: System.TArray<System.TCustomAttribute>;const ASerializationAction: TMVCSerializationAction = nil);
procedure DeserializeAttribute(var AElementValue: TValue; const APropertyName: string; const ASerializerObject: TObject; const AAttributes: System.TArray<System.TCustomAttribute>);
procedure DeserializeRoot(const ASerializerObject: TObject; const AObject: TObject;const AAttributes: System.TArray<System.TCustomAttribute>);
end;
我注册了序列化程序
var lSerializer: IMVCSerializer := TMVCJsonDataObjectsSerializer.Create;
lSerializer.RegisterTypeSerializer(TypeInfo(TFoldedList<System.TObject>), TListSerializer.Create);
IList<TPerson>
是一个TFoldedList<System.TObject>
评论
IList
IList