I have developed application for drawing some shapes (lines mostly) , now i need to be able to store sketch to a file, I know that delphi has build in routines for object persistence, but I have never used it.
Can someone tell me can object persistence be used if i have to persist object that have also references to other objects (that will be stored to), I have TLine object which can be connected to other TLine object etc.
Is it better to use this feature or write custom procedure to store/read object to/from file.
The built in object persistance is primarily designed for use in streaming components to a dfm, the work that you would need to do to persist your sketch would not benefit very much from that mechanism.
I think that you would be better off coming up with a custom scheme.
One method that I have used in the past is to store my object properties in an XML file writing a custom "save" routine which adds to a passed IXMLNode, and a new constructor which reads from a passed IXMLNode. I store component as a node, and the properties as attributes (unless the property is another object, then it would be a child node).
I believe there are some routines in the Delphi Jedi project which will handle component streaming for you, but I have not used them directly as most of my XML streaming has been done by hand since my objects were extremely simple and could be rendered with only a handful of properties.
I use the TI Object persistence framework (tiopf.com). I wrote the overview at http://tiopf.sourceforge.net/Doc/overview/index.shtml.
It will let you save objects and lists to xml, csv, databases etc. It handles child objects automatically.
If you are interested, use the svn version, not the sourceforge download as it has more features (inc partial D 2009 support).
You also can use the famous hibernate know from java.
the delphi port you can find here:
dHibernate
JSON is a new and very compact way to store objects. Two libraries are available for Delphi: SuperObject and lkJSON.
With NativeXML from http://www.simdesign.nl/xml.html I accomplished to read/write delphi in-memory objects from/to XML code. Very nice, very easy, with demo included here: http://www.simdesign.nl/forum/download/file.php?id=236
Related
I am planning to move away from BDE and dBase so, while implementing some application I need to stay away from everything that could make the transition more difficult. I wonder, for instance, if data aware components like TDBCtrlGrid is toot tied in some way to the BDE or not.
Db-aware components like the TDBCtrlGrid, TDBGrid, TDBEdit, etc, should all work fine with more modern TDataSet-descendants than TQuery, TTable, etc. So the answer to your q is that they are all generic.
The whole point of the design of Delphi's db-aware components is that the access model they use is abstracted from any particular dataset implementation and so will work with any TDataSet descendant, because TDataSet itself implements an abstracted data-access model.
Delphi's db-aware components work at two steps removed from TDataSet, and interact with it (or any descendant of it) via TDataSource and TDataLink and its descendants. All data interactions occur via TDataLinks - see the source in DB.Pas.
Short answer is no : TDBCtrlGrid is not tied to the BDE.
TDBCtrlGrid is populated by a "dataset" or, if you prefer, by a TDataSet which is an abstract class providing the basic properties, events, and methods for working with data.
There are many implementations of TDataSet which will allow you to use whatever data base engine you want.
From the doc here are some popular TDataSet implementations :
TCustomADODataSet is the base class for datasets that access their
data using ActiveX Data Objects (ADO). TCustomADODataSet descendants
include TADODataSet, TADOTable, TADOQuery, and TADOStoredProc.
Developers who create custom dataset components that use ADO derive
them from CustomADODataSet.
TIBCustomDataSet is the base class for datasets that directly access
the data in InterBase tables. TIBCustomDataSet descendants include
TIBDataSet, TIBTable, TIBQuery, and TIBStoredProc. Developers who
create custom dataset components that directly access data in an
InterBase database derive from TIBCustomDataSet.
TCustomSQLDataSet is the base class for unidirectional datasets.
Unidirectional datasets are read-only datasets that permit only
forward navigation. TCustomSQLDataSet descendants include the
dbExpress datasets TSQLDataSet, TSQLQuery, TSQLTable, and
TSQLStoredProc. Developers who create custom dataset components that
use dbExpress to access their data derive from TCustomSQLDataSet.
TCustomClientDataSet is the base class for in-memory datasets. Client
datasets can work with data from files on disk or with data provided
by another component via a provider. They cache that data in memory,
maintain a record of any changes in a change log, and apply cached
updates at a later point back to the source of the data. Developers
who create custom datasets that store their data in an in-memory cache
derive from TCustomClientDataSet.
I would investigate several databases including some of the latest in the Delphi version you currently use. That includes Mongo if you have the latest.
For productivity Firedac is quite good. It codes like ADO and performs almost as well as GO.
In general I suggest getting Nick Hodges' book and start using Spring4D.
If that is too deep for you then Firedac is a good starting point.
In Java, one can save a serializable object to a file and load an object from that file. Can we do this in Delphi? If yes, How?
If you ask "Can we do this in Delphi?" - the answer is: yes. I guess you want to know, HOW this can be done in Delphi? Well this depends on what do you want to serialize:
If you want to serialize
your own data objects, then you could
write your own saveTo/loadFrom functions
components, then you could use the built-in component streaming system
any unknown object, then you need some RTTI techniques and the objects must publish their serializable properties
http://blog.dragonsoft.us/2008/04/21/how-to-serialize-delphi-object/
DeHL: http://alex.ciobanu.org/?p=285
The first article linked to by Andre seems (maybe I skimmed to fast) to use the "old" pre-D2010 style RTTI (Run-Time Type Information), which is dependent on properties having published visibility in order to be able to enumerate them.
As of D2010 Delphi has a completely new extended RTTI (built on top of the old one) which does not require published visibility and does a lot more than enumerate properties. DeHL, as described in the second article linked to be Andre, does use the new RTTI, and if you are looking for a library, I would also recommend this library.
If you prefer to build your own, you could have a look at an article on XML-serialization using the new RTTI by Robert Love: http://robstechcorner.blogspot.com/2009/10/xml-serialization-basic-usage.html
Robert Love also has a nice overview of RTTI articles: http://robstechcorner.blogspot.com/2009/09/so-what-is-rtti-rtti-is-acronym-for-run.html
And for some more ideas on what can be done with the new style RTTI, have a look at
Practical usage for Delphi's new RTTI - Attributes,Values and Why should I care about RTTI in Delphi?
NativeXML NativeXML website has the ability to store/retrieve objects in an XML format, which gives you additional manipulation capability over the RTTI methodology. Fast and easy manipulation of XML documents and the added capability of saving/loading persistent objects.
We’re rewriting a calculation core from scratch in Delphi, and we’re looking for ways to let other people write code against it.
Automation seems a fairly safe way to get this done. One use we’re thinking of is making it available to VBA/Office, and also generating a .NET assembly (based on the Automation object, that's easy).
But the code should still be easy to use from Delphi, since we’ll be writing our (desktop) UI with that.
Now I’ve been looking into creating an Automation server in Delphi, and it looks like quite a hassle to have to design the components in the Type Library wizard, and then generate the base code.
The calculations we’re having to implement are described in official rules and regulations that are still not ratified, and so could still change before we’re done — they very probably will, perhaps quite extensively. Waiting for the final version is not an option.
An alternative way could be to finish the entire object model first, and write a separate Automation server which only describes the top-level object, switch $METHODINFO ON, and use TObjectDispatch to return all the subordinate objects. As I see it, that would entail having to write wrappers to return the objects by IDispatch interface. Since there's over a 100 different classes in there, that doesn’t look like an attractive option.
Edit: TObjectDispatch is smart enough to wrap any objects returned by properties and methods as well; so only the top object(s) would need to be wrapped. Lack of a complete type library does mean only late-binding is possible, however.
Is there an other, easier (read: hassle-free) way to write a COM-accessible object model in Delphi?
You don't have to use the type library designer. You can write or generate (e.g. from RTTI of your Delphi classes) a .ridl file and add it to your Automation library project.
Generating interface description from RTTI is a great idea! After you have your interfaces generated you can generate a delphi unit from them and implementing in your classes. Of course the majority are implemented already since you have generated the interfaces from those classes after all. The late binding resolution can be done after that by hand using RTTI and implementing IDispatch and IDispatchEx in a common baseclass of the scriptable classes.
One of the projects I'm working on involves a module that needs to allow end users to create what essentially equates to, their own "object classes," storing data structures / record types that they can design and modify at runtime. The users will also be able to customize the user interface considerably, but that is not so much the scope of this question.
The closest example to what we are striving to build with this functionality, that I've seen, would be something very akin to what InstantObjects provides at design time, except our system would provide it at runtime, and put the class design control in the hands of the end-user (who will generally be pretty technically sophisticated, obviously).
I recently came across this list of Object Persistence Frameworks for Delphi Win32:
http://tdelphihobbyist.blogspot.com/2008/01/win32-object-persistence-frameworks.html
Any recommendations as to which of these might be the most conducive to the kind of runtime flexibility we are trying to create?
There is currently ongoing discussion of this in the tiopf newsgroups. Tiopf is a open source object persistence framework. Currently it doesn't support user modifiable objects but it looks like someone will be adding this functionality shortly.
Main site: http://tiopf.sourceforge.net/
News groups: See http://tiopf.sourceforge.net/Support.shtml
See "tiOPF ad runtime modifications" thread in the support newsgroup.
JSON could be used to declare and modify user-defined data structures at runtime. There are two libraries for Delphi, SuperObject and lkJSON. With JSON, object hierarchies would be easy to build. The SuperObject demo sources include examples for many usage areas.
SuperObject also contains iterator methods for a given JSON object structure.
I use it for a Delphi client library which is able to exchange objects with Java using the ApacheMQ message broker.
You can create some form of persistence using xml and then buil a form acordingly, we do this a lot for configurable filter windows for example
Has anyone run into issues serializing components into a file and reading them back, specifically in the area where the component vendor upgrades the VCL components. For example a file serialized with DelphiX and then years later read back with delphiY. Do the serialization formats change and if so what can be done to prevent errors reading in the componets when upgrading.
The built-in RTTI based system for serializing published properties is vulnerable to changes in the components. Going forwards is manageable as long as old properties are kept in new objects. I.e. you leave the property interface as is, but can toss away the contents if you like. Going backwards is worse - as a newer version saved property can't be opened in older version load, and that will be a problem.
There are components / libs (http://www.torry.net/quicksearchd.php?String=RTTI&Title=Yes) that can add serialization in XML format and this may help a bit as you can choose to skip content you don't know.
You still need to be mindful about how you design your published content and should probably find a way to "ignore but propagate" content that your current version don't understand. This will allow you to open and change a file in a newer format while attempting to keep newer attributes, instead of stripping them.
Formats will defintely change, as vendors will add features to their components. Serialization simply loops over all published properties and saves them to a stream. When they are read back, each of the properties that is read from the stream will be set back to the component. If the property does not exist anymore, you have a problem. I don't think you can do anything about that besides some basic exception handling.
Best way to guarantee compatibility is to do your own serialization.
Thanks for the reply. I was trying to avoid custom serialization and take advantage of the each component serialization technique, but with the lack opf any way to "patch" an upgrade to a new component format I guess custom serialization is the only method.