DeHL Library

DeHLDeHL project aims to create a useful code library for Delphi 2010+ platform.



The most important features of DeHL for now are:

  • A set of generic collections classes (TList, TDictionary, THashSet, TMultiMap, TPriorityQueue and etc).
  • Linq-like extensions (called Enex) for collections which allow writing queries on collection classes.
  • Date/Time functionality all combined in a few structures (somehow equivalent to .NET’s DateTime structure)
  • Type Support concept that defines a set of default “support classes” for each built-in Delphi types (used as defaults in collections). Custom “type support” classes can be registered for your custom data types.
  • BigCardinal and BigInteger data types.
  • Scoped objects in Delphi.
  • Nullable types in Delphi.
  • Array extensions and utilities.
  • Wide charset implementation.
  • Full generic serialization for all included types and collections
  • … and more!

All classes and functions have unit tests. We’re trying to maintain a large set of tests to find and fix early all possible bugs. You can find more information about the library here: FeatureList For more information about the design goals see Introduction

All the source code is BSD licensed — you’re free to use it in any commercial application with no restrictions.

21 Responses to 'DeHL Library'

  1. WojTec says:

    I don’t know where to download it?

  2. Warren says:

    Are there code-samples somewhere for DeHL?

    Warren

  3. alex says:

    @Warren
    Not yet I am afraid. Don’t have enough free time to do them.

  4. Wodzu says:

    Alex, would you mind if some users will try to port your library to the FPC?

  5. alex says:

    It’s BSD-licensed. You can do almost anything to it. But I must warn you – you will most likely fail to port more than a few classes. AFAIK FPC doesn’t support D2010 features (which now stay at the core of the library). Also I don’t know if the generics model is compatible.

  6. Tim Kelly says:

    Problem 1
    ————-

    Hmmm… Serialization of interfaces isn’t quite working as expected:

    IFoo = interface(ISerializable)

    end;

    TFoo = class(TInterfacedObject, IFoo)
    procedure Serialize(const AData: TSerializationData);
    procedure Deserialize(const AData: TDeserializationData);

    end;

    TTest = class
    FFoo : IFoo;
    public
    constructor Create;
    end;

    { TFoo }

    procedure TFoo.Deserialize(const AData: TDeserializationData);
    begin
    //
    end;

    procedure TFoo.Serialize(const AData: TSerializationData);
    begin
    //
    end;

    { TTest }

    constructor TTest.Create()
    begin
    FFoo := TFoo.Create;
    end;

    Now when I pass a copy of TTest to the serializer (as per your example http://alex.ciobanu.org/?p=285) I get:

    “The entity FFoo of type IFoo does not define any serialization/deseriazlion method.”

    This seems strange to me as IFoo is inherited from ISerializable.

    I prefer using interfaces as fields in my classes as I don’t need to worry about freeing them. This example works fine if I change FFoo : IFoo -> FFoo : TFoo in TTest.

    Problem 2
    ————

    By the way I discovered this during investigating another serious problem: I can’t get any of your collection interfaces to serialize naturally (ie. if they are fields in TTest.)

    Originally I suspected this was because your base collection interface isn’t derived from ISerializable but having manually changed your code to inherit from ISerializable

    Problem 3
    ————-
    Finally… I don’t get something. In your example (http://alex.ciobanu.org/?p=285), TTest is not supporting ISerializable but yet we can serialize it. So why must you insist that member object fields are ISerializable why can’t we just apply the same process to them that is being applied to TTest?!

    —-

    Thanks for your help in advance. Am I being really stupid?

  7. Tim Kelly says:

    Regarding problem 3 actually I notice that in fact member fields don’t need to be ISerializable after all…. the other problems still stand though.

  8. alex says:

    @Tim Kelly
    Hi Tim., simple answer: interfaces are not serializable. Serialization in my current implementation has to be paired with deserialization. Since an Interface is not bound to any object type, you cannot know the type of the actual object behind it (not without breaking OOP concepts at least) so you cannot deserialize it. What you are seeing is exactly what it says – no serialization method defined for interface types.

    As for classes, ISerializable is used to supply you own serialization code if you so choose. The default serialization method (by going recursively) is used on all classes if those do not provide their own ISerializable code.

  9. Tim Kelly says:

    I am VERY impressed by your library. It should be bundled with Delphi – I can’t imaging coding without it now! One question: I’ve been having a lot of problems with debugging classes nested in generics due to QC bug 84930 (debugger crashes). Given that you have coded a complex library which includes nested generics I was just wondering if a) you have come across this bug and more importantly b) if you have found a work-around / patch for it?

    Life without a debugger is not fun!

  10. alex says:

    Thank you!

    I employ different techniques when I find these debugging problems, but it mostly works. The newer Delphi versions are pretty stable in this regard.

    Alex.

  11. Tim Kelly says:

    I am trying to make an OwnedObject dictionary (I need a fash object hash). I want the key to be a string and I want the hash to Own the objects. I didn’t seem to get much luck doing a TObjectDictionary as it doesn’t like the key being a string, rather than an object…. please help!

  12. Tim Kelly says:

    Whoops.. sorry to bother you again… but i’m a bit stuck… I’ve got a list of customobjects and I want to sort them but I don’t quite get how I define the compare algorithm to make one higher in the list over another….

  13. alex says:

    @Tim Kelly
    Tim, send me an email at alex [at] ciobanu [dot] org. I’ll try to respond with some explanations or I will update DeHL accordingly.

    Alex.

  14. William Meyer says:

    Alex, I have been reading your blog and noticed some mention of documentation you’ve begun. I’d like to see it, though I’m sure you have little time for the writing. Perhaps if it helps me learn the package, I may be able to contribute some writing….

  15. alex says:

    @William Meyer
    I will start working on documentation for the 1.0 release. 1.0 will be the stable one in which I am not going to change interfaces. The next release is 0.9 so the documentation is following (0.9 -> 1.0 will be only about docs).

  16. Great stuff! I will watch this one :)

  17. Lee Griffin says:

    I love your serialization classes! However, it doesn’t seem as though, when serializing an object based on your TObjectList generic, that it serializes the “OwnsObjects” property. I need it to serialize the property and properly set that value on deserialization.

    Is this working as designed? Can you inform me as to how to get the serialization/deserialization of OwnsObjects to work? I’ve tried simple stuff like making it published. I tried to dig into your code, but it went waaaaay to deep for me.

    Any help you can give me will be greatly appreciated.

    Lee Griffin

  18. alex says:

    @Lee Griffin
    Simply put, you should never serialize that value. OwnsObjects is an internal thing and should be controlled by the application and not by the serialized data. But if you really want to:

    1. Derive from TObjectList … say TYourList
    2. Override StartSerializing and StartDeserializing methods:
    procedure StartSerializing(const AData: TSerializationData); override;
    procedure StartDeserializing(const AData: TDeserializationData); override;

    3. Implement those method as following:
    procedure TYourList.StartDeserializing(const AData: TDeserializationData);
    var
    LOwns: Boolean;
    begin
    AData.GetValue(‘OwnsItsObjects’, LOwns);
    OwnsObjects := LOwns;

    inherited;
    end;

    procedure TYourList.StartSerializing(const AData: TSerializationData);
    begin
    AData.AddValue(‘OwnsItsObjects’, OwnsObjects);

    inherited;
    end;

    “OwnsItsObjects” is the name given to the serialized property … you can use any other name.

  19. Lee Griffin says:

    @alex
    Thank you! That’s just what I was looking for.

    With regards to “never serialize that value”, the way I will be using the lists is that I will have lists of lists of lists (etc.). When I deserialize the lists, the application whould have to traverse the entire heirarchy, setting each list’s “OwnsObjects”. It would be simpler if I could serialize the value–and I can now because of your suggestion.

    I’ve been trying to implement a serialization mechanisim for months and never quite got it right. Your routines are just what I have been needing. Thank you so much for them and your help!

    Lee

  20. alex says:

    @Lee Griffin
    Glad I could help.

    Note that external factors can modify the value of that property in the serialized medium and then your app’s behavior is modified.

    If you have suggestions, bugs or any other subjects to discuss email me directly. You can find the email in about section (I don’t list it here for spam protection purposes).

Leave a Reply

Your email address will not be published.