#1 2013-07-30 13:07:55

Stefan
Member
Registered: 2012-11-23
Posts: 26

Handle other collection types in mORMot?

Does the framework support JSON serialization for custom collection types (I am thinking of IList<T>)?

Last edited by Stefan (2013-07-30 13:08:26)

Offline

#2 2013-07-30 13:31:41

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Handle other collection types in mORMot?

Not yet, since our main Delphi platform is not using generics.

But we started adding some generic-based methods.
It is possible to add such support.

Which kind of generic types do you need?
We need to retrieve the T type from an instance of IList<T>.
Is T a simple type (like string, integer, record) or a managed type (like class or interface)?

Do you have some code to propose?

Offline

#3 2013-07-30 14:04:13

Stefan
Member
Registered: 2012-11-23
Posts: 26

Re: Handle other collection types in mORMot?

You can take a look at Spring4d as I was talking about those IList<T> types (http://code.google.com/p/delphi-spring- … ctions.pas).

IList<T> inherits from IEnumerable which has the GetElementType method that returns the PTypeInfo of T.
T can basically be any type but I am mostly interested in class types.

So I can write a service that has methods like:

function LoadCustomers(out customers: IList<TCustomer>): Boolean

But this already fails at startup because interface parameters are currently not supported.

Last edited by Stefan (2013-07-30 14:04:35)

Offline

#4 2013-07-30 14:27:43

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Handle other collection types in mORMot?

If I follow your mind, a IList<TCustomer> will be serialized as an array of TCustomer objects, right?
It sounds very nice.

In fact, interfaces are not implemented at service level, since it is difficult to find on client side how to implement all methods of the interface, since the implementation class reside on the server...

Of course, we can make an exception for such kind of interface.
So here, we will need a fixed class type to implement IList<>.

So we would need a IEnumerable type with its own GetElementType() method...

I suspect we may have to integrate mORMot to work natively with the Delphi Sprint framework classes, if we want proper generic support.
Your implementation seems much more advanced than the one available in "plain" Delphi RTL.

Offline

#5 2013-07-31 06:07:03

Stefan
Member
Registered: 2012-11-23
Posts: 26

Re: Handle other collection types in mORMot?

I wonder if you can take advantage of the enumerator for serializing and the existence of the GetElementType and the Add method for deserializing.

Much like I have done for XML serialization:
TXmlWriter.WriteEnumerable and TXmlReader.ReadEnumerable

I think an array of objects currently is not supported also, isn't it?

Serverside you can use an implementation like this:

uses
  Spring.Collections,
  Spring.Collections.Lists,
  TypInfo;

type
  TList = class(TObjectList<TPersistent>)
  private
    fElementType: TClass;
  protected
    function GetElementType: PTypeInfo; override;
  public
    constructor Create(elementType: TPersistentClass);
  end;

constructor TList.Create(elementType: TPersistentClass);
begin
  inherited Create;
  fElementType := elementType;
end;

function TList.GetElementType: PTypeInfo;
begin
  Result := fElementType.ClassInfo;
end;

Using it would be like this:

var
  list: IList<TCustomer>;
begin
  IList<TPersistent>(list) := TList.Create(TCustomer);
  list.Add(TCustomer.Create);
end;

As you can see this is code that can be invoked dynamically as it does not involve any generics anymore (given the restriction that only IList<T: TPersistent> is allowed as parameter.

It could also be TObject if the JSONObject routine would allow TObject (which can have the $M+ be defined - which happens automatically when adding published properties)

Last edited by Stefan (2013-07-31 06:36:02)

Offline

#6 2013-07-31 06:34:43

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Handle other collection types in mORMot?

Stefan wrote:

I wonder if you can take advantage of the enumerator for serializing and the existence of the GetElementType and the Add method for deserializing.

IMHO so much relying on the RTTI makes it damn slow.

Stefan wrote:

I think an array of objects currently is not supported also, isn't it?

No, but honestly an array of objects is a bit weird.

I do not see much benefit of this IList<> kind of structures in comparison to the existing content.
And in the current implementation, both TList and TObjectList are supported by ObjectToJSON().
On its side, JSONToObject() is already able to un-serialize a TObjectList class, when a class type is supplied as TObjectListItemClass optional parameter for its items, or if a "ClassName": member is already present at JSON serialization level.
So you are already able to serialize/unserialize any TObjectList (or inherited) instances, thanks to the internal class registration mechanism...

Offline

#7 2013-07-31 06:44:57

Stefan
Member
Registered: 2012-11-23
Posts: 26

Re: Handle other collection types in mORMot?

ab wrote:

I do not see much benefit of this IList<> kind of structures in comparison to the existing content.
And in the current implementation, both TList and TObjectList are supported by ObjectToJSON().
On its side, JSONToObject() is already able to un-serialize a TObjectList class, when a class type is supplied as TObjectListItemClass optional parameter for its items, or if a "ClassName": member is already present at JSON serialization level.
So you are already able to serialize/unserialize any TObjectList (or inherited) instances...

The problem is when the client side exclusively works with IList<> as our software currently does (would be the same if we were using the Generics.Collections ones though). That would mean extra work to create wrappers which mORMot can work with.
So the better way imo would be to work with these types directly. So what this needs is some mechanism to register custom types if you don't want the framework to have more dependencies than needed (which I understand) - I guess this is also responsible for creating the instances on the server side (haven't looked into it yet).

Of course with generics this is a bit more complicated as you cannot just register a type info.

Last edited by Stefan (2013-07-31 06:49:42)

Offline

#8 2013-07-31 07:07:12

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Handle other collection types in mORMot?

Stefan wrote:

I guess this is also responsible for creating the instances on the server side (haven't looked into it yet).

Yes, it is the case: there is a way to create instances from any class type (including virtual constructor, if needed)./

Stefan wrote:

Of course with generics this is a bit more complicated as you cannot just register a type info.

This is my main concern.

Offline

#9 2013-07-31 07:52:43

Stefan
Member
Registered: 2012-11-23
Posts: 26

Re: Handle other collection types in mORMot?

The thing is TObjectList and not typesafe and ugly to use in client side code (yes, can write typesafe derived classes for that but come on...) and already on the way of getting removed from the RTL (only for nextgen though but anyway) and TCollection requires the items to be inherited from TCollectionItem which may not be possible.

Let's do it step by step - I can register custom json serializers if I want for example to use Generics.Collections.TList<TCustomer>, right?
How does that work?

Last edited by Stefan (2013-07-31 07:53:30)

Offline

#10 2013-07-31 08:29:31

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Handle other collection types in mORMot?

Check out the updated 1.18 documentation, or just http://blog.synopse.info/post/2012/04/1 … -any-class

I'm still not converted by this "NextGen" lazy definition: we get rid of most which makes Delphi a distinctive environment, just to reduce EMB dev costs?
What about the existing code base?
Getting rid of TObjectList will break a lot of existing code.

Why on earth does not TObjectList<T> have a member to retrieve the type information about T ?
Half backed "new" RTL? Or just because it does not exist in C# (which does not need it)? But sounds to be mandatory for Delphi.

Offline

#11 2013-07-31 21:00:59

Roberto Schneiders
Member
From: Santa Catarina, Brazil
Registered: 2012-09-19
Posts: 127
Website

Re: Handle other collection types in mORMot?

Why on earth does not TObjectList<T> have a member to retrieve the type information about T ?

I had this same problem today! It's unfortunate.

I solved getting the type of the "First" method.

Rtti.GetType(ObjectList.ClassInfo).GetMethod('First').ReturnType

I know, it's very strange. But so far I have not found a better way.

Offline

#12 2013-08-01 11:17:51

Stefan
Member
Registered: 2012-11-23
Posts: 26

Re: Handle other collection types in mORMot?

The problem in this case is not even the missing member of the class type.
What is missing is additional RTTI for generic types (like the typeinfo for the generic parameters) just similar to the information you get for array types.

When you have a argument of the type IList<TClient> you have to retrieve the type info for TClient to be able to create instances of that class when deserializing.

In that case you can use a class like I posted above.

Currently afaik you only can get the generic parameter by analyzing the class name (in our example extract the TClient from IList<TClient> and then iterate all known types and compare it - but even then you cannot be sure if you get the correct type unless its a public type which is fully qualified).

Anyway I got the IList<T> support partially working - just trying to solve the problem I just explained.

Offline

#13 2016-03-16 19:33:13

edwinsn
Member
Registered: 2010-07-02
Posts: 1,218

Re: Handle other collection types in mORMot?

@Stephen, @ab,

Regarding:

So I can write a service that has methods like:
function LoadCustomers(out customers: IList<TCustomer>): Boolean
But this already fails at startup because interface parameters are currently not supported.

Is the issue fixed, can we use the Spring4D collection in a mORMot service now?


Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.

Offline

#14 2016-03-16 19:38:06

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Handle other collection types in mORMot?

No, this is not fixed/implement, since
- we don't use such collections, but T*ObjArray
- it sounds like a limitation of the Delphi RTTI

Offline

Board footer

Powered by FluxBB