泛型和 Marshal/UnMarshal。我在这里缺少什么?第 #2 部分:-)
跟进我之前的问题: 泛型和 Marshal / UnMarshal。我在这里缺少什么?
在“第 1 部分”(上面的链接)中,TOndrej 提供了一个很好的解决方案 - 但在 XE2 上失败了。 在这里我提供了更正的来源来纠正这个问题。
我觉得有必要进一步扩展这个问题。 所以我想听听大家如何做到这一点:
首先 - 要让源代码在 XE2 和 XE2 更新 1 上运行,请进行这些更改:
Marshal.RegisterConverter(TTestObject,
function (Data: TObject): String // <-- String here
begin
Result := T(Data).Marshal.ToString; // <-- ToString here
end
);
为什么? 我认为与 XE2 相关的唯一原因是有更多的 RTTI 信息可用。因此它将尝试封送返回的 TObject。 我走在正确的轨道上吗?请随意发表评论。
更重要 - 该示例未实现 UnMarshal 方法。 如果有人可以制作一个并将其发布在这里,我会很高兴:-)
我希望您仍然对这个主题感兴趣。
亲切的问候 比亚内
Following up on my earlier question :
Generics and Marshal / UnMarshal. What am I missing here?
In "part #1" (the link above) TOndrej provided a nice solution - that failed on XE2.
Here I provide corrected source to correct that.
And I feel the need to expand this issue a bit more.
So I would like to hear you all how to do this :
First - To get the source running on XE2 and XE2 update 1 make these changes :
Marshal.RegisterConverter(TTestObject,
function (Data: TObject): String // <-- String here
begin
Result := T(Data).Marshal.ToString; // <-- ToString here
end
);
Why ??
The only reason I can see must be related to XE2 is having a lot more RTTI information available. And hence it will try and marshal the TObject returned.
Am I on the right track here? Please feel free to comment.
More important - the example does not implement an UnMarshal method.
If anyone can produce one and post it here I would love it :-)
I hope that you still have interest in this subject.
Kind Regards
Bjarne
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
除了这个问题的答案之外,我还在这里发布了您上一个问题的解决方法:泛型和 Marshal / UnMarshal。我在这里缺少什么?
由于某种原因,使用 TJsonobject 的非默认构造函数会导致 XE2 中出现问题 - 使用默认构造函数“修复”了该问题。
首先,您需要将 TTestobject 移动到其自己的单元 - 否则,RTTI 在尝试解组时将无法找到/创建您的对象。
另请注意,构造函数已被重载 - 这使您可以看到代码可以正常运行,而无需在创建过程中预先填充对象中的数据。
这是泛型类列表对象的实现
有几件事需要注意:
如果在运行时创建通用类,则不会保留 RTTI 信息,除非内存中有对该类的全局可访问对象引用。请参阅此处: Delphi:RTTI 和 TObjectList
因此,上述单元创建了这样一个变量并按照链接文章中的讨论将其实例化。
主要过程已更新,显示了两个对象的数据编组和解组:
In addition to the answer to this question, I've posted a workaround to your previous question here: Generics and Marshal / UnMarshal. What am I missing here?
For some reason, using the non-default constructor of the TJsonobject causes the issue in XE2 - using the default constructor "fixed" the problem.
First, you need to move your TTestobject to its own unit - otherwise, RTTI won't be able to find/create your object when trying to unmarshal.
Also note that the constructor has been overloaded - this allows you to see that the code is functional without pre-pouplating the data in the object during creation.
Here is the implementation for the generic class list object
There are several things that are important to note:
If a generic class is created at runtime, RTTI information is NOT kept unless there is a globally accessible object reference to that class in memory. See here: Delphi: RTTI and TObjectList<TObject>
So, the above unit creates such a variable and leaves it instantiated as discussed in the linked article.
The main procedure has been updated that shows both marshaling and unmarshaling the data for both objects:
这是我自己的解决方案。
由于我非常喜欢多态性,所以我实际上也想要一个可以构建到对象层次结构中的解决方案。假设 TTestObject 和 TTestObjectList 是我们的 BASE 对象。从这里我们下降到 TMyObject 和 TMyObjectList。此外,我还对对象和列表进行了更改 - 为 Marshaller/UnMarshaller 添加了属性,
现在我们引入了一些新问题。 IE。如何处理层次结构中各行之间不同类型的编组,以及如何将 TJsonMarshal 和 TJsonUnMarshal 作为 TTestObject 和 List 上的属性进行处理。
这可以通过在 TTestObject 级别引入两种新方法来克服。两个类函数称为 RegisterConverters 和 RegisterReverters。然后我们着手将 TTestObjectList 的编组函数更改为更简单的编组。
对象和列表的两个类函数和属性。
List 的 Marshal 函数现在可以像这样完成:
当然,我们仍然可以为 TTestObject 有一个编组器 - 但 TTestObjectList 的 Marshal 函数不会使用它。这样,当调用 TTestObjectList(或后代)的 Marshal 时,只会创建一个 Marshaller。这样,我们最终只会编组我们在向后执行所有操作时重新创建结构所需的信息 - UnMarshalling :-)
现在这实际上有效 - 但我想知道是否有人对此有任何评论?
让我们向 TMyTestObject 添加属性“TimeOfCreation”:
属性 TimeOfCreation :TDateTime 读取 FTimeOfCreation 写入 FTimeOfCreation;
并在构造函数中设置属性。
然后我们需要一个转换器,因此我们重写 TTestObject 的虚拟 RegisterConverters。
我最终得到了非常简单的源代码,例如使用 TTestObject ie。
现在我已经成功地进行了多态性编组:-) 顺便说一句,
这也适用于 UnMarshalling。我正在重建我的 FireBird ORM 来为我的所有对象生成源代码,就像这样。
当前的旧版本可以在这里找到:
http://code.google.com/p/objectgenerator/
请记住,它仅适用于 FireBird :-)
Here is my own solution.
As I am very fond of polymorphism, I actually also want a solution that can be built into an object hierarchy. Lets say TTestObject and TTestObjectList is our BASE object. And from that we descend to TMyObject and also TMyObjectList. And furthermore I've made changes to both Object and List - added properties for Marshaller/UnMarshaller
With this we now introduce some new problems. Ie. how to handle marshalling of different types between lines in the hierarchy and how to handle TJsonMarshal and TJsonUnMarshal as properties on TTestObject and List.
This can be overcome by introducing two new methods on TTestObject level. Two class functions called RegisterConverters and RegisterReverters. Then we go about and change the marshal function of TTestObjectList into a more simpel marshalling.
Two class functions and properties for both object and List.
The Marshal function of List can now be done like this:
Sure we can still have a marshaller for our TTestObject - but the Marshal function of TTestObjectList will NOT use it. This way only ONE Marshaller will get created when calling Marshal of TTestObjectList (or descendants). And this way we end up getting marshalled ONLY the information we need to recreate our structure when doing it all backwards - UnMarshalling :-)
Now this actually works - but I wonder if anyone has any comments on this ?
Lets add a property "TimeOfCreation" to TMyTestObject:
property TimeOfCreation : TDateTime read FTimeOfCreation write FTimeOfCreation;
And set the property in the constructor.
And then we need a Converter so we override the virtual RegisterConverters of TTestObject.
I end up with Very simple source like using TTestObject ie.
And now I have succeded in marshalling with polymorphism :-)
This also works with UnMarshalling btw. And Im in the process of rebuilding my FireBird ORM to produce source for all my objects like this.
The current OLD version can be found here :
http://code.google.com/p/objectgenerator/
Remember that it only works for FireBird :-)