I'd like to compare the "state" of two components, say Comp1: TSomeComponent and Comp2: TSomeComponent, i.e. I want to compare the values of all the published properties of the two components. Some of the properties are indexed, like the TListBox.Items property. Is there an easy way to do this? Do I have to invoke some iterating RTTI code?
An easy way would be to serialize them both with WriteComponent and compare the resulting strings. Note, however, that this would compare only published, not public, properties. But that is what you say you need, so...
Note that this would make, say, the order of the indexed properties significant. That may or may not be what you want.
Unfortunately, there's no simple compare function in Delphi as far as I know. (I've stopped at D2007.) You could add a method "Compare" to the base class and build the comparison of all fields inside this method. (It should accept one parameter of the same base class.) With D2007 you could build this as a helper class, but you still need to specify the fields.
Other classes could be inherited from this base class and override the base Compare method.
The use of RTTI will make it easier to compare fields of classes from different types but it's complex and error-prone. It will require a lot of testing with all kinds of different classes.
A trick I use (but I would like to have something like this integrated in the IDE) is to copy the dfm part related to the 2 components (using ALT+F12) to access dfm and then I paste the 2 components in NotePad++ and I use the Compare Plugin to compare the 2.
It gives a nice visual output, but this takes more time than selecting more components in the IDE (even from different windows) and then Compare them with a compare tool built in in the IDE.
Related
I'm working with Delphi 10.4.
At some places of my code I have to write long identifiers on long statements (e.g. ProductsForSale.fieldByName('quantity').asInteger * ..... / .... etc.). Is there a way to assign a friendly alias (e.g. TheCost) to this piece of code to substitute it everywhere in the application?
I don't want to use a variable or a function to do this. Only text substitution.
No, Delphi (and Pascal) knows
neither aliases (using a different name for a type/variable/function still needs you to define it anew),
nor macros (executing code in the compiler's context is very limited, mostly definings and conditions).
Even if, chances are you'd have to define it bound to a given context/scope: i.e. your favorite alias TooMuchToType might access three variables named one, two and three, but as per scope those variable's types can vary drastically. Its usage would be prone to obfuscated code and a lot of hassle the compiler has to go thru when trying to give you an error message he wants you to understand.
Why not doing exactly that at the end, but in the opposite way? First using a placeholder and when you're done you replace all of them with the actual code. Otherwise this is bascially what functions are there for, if you want it or not.
I was looking at the source code for the Append function in the SeqModule and noticed that there are a ton of duplicate methods with #xxx postfixed to them. Does anyone know why these are here?
In short, those are the concrete classes that back various local function values, and the #xxx values indicate the source code line number that caused them to be generated (though this is an implementation detail, and the classes could be given any arbitrary name).
Likewise, the C# compiler uses a conceptually similar scheme when defining classes to implement anonymous delegates, iterator state machines, etc. (see Eric Lippert's answer here for how the "magic names" in C# work).
These schemes are necessary because not every language feature maps perfectly to things that can be expressed cleanly in the CLR.
Digging into a legacy project (C++) that needs to be extended, I realized that there are about 40 reader/writer/parser classes. They are used to read and write various type of data (different objects) in different files format (binary, hdf5, xml, text, ...) ; one type of object is typically bound to one or two file formats. The classes have for most of them just no knowledge of the others. Interfaces and inheritance were apparently unknown to the writer, as well as design patterns.
It seems to me an horrendous mess. On the other hand I am not exactly sure how to handle this situation. I will at least extract interfaces. I would also like to see if I can have common code in some parent classes, for example what is specific to a hdf5 reader/writer. I also thought that the abstract factory pattern could help but the object I get out of the readers are completely different.
How would you handle this situation ? how would you design the classes ? what design pattern would you use if any ? Would you keep the reading and writing parts splitted ?
The Abstract Factory pattern isn't the right track. You usually only need interfaces if you anticipate multiple implementations for a given file type and want both to operate the same way.
Question: can one class be written to multiple file types? As in, object 'a' (of type Class A) potentially needs to be written to either/both XML or text formats?
If that is true, you need to decouple the classes from the readers/writers. Take a look at this question: What design pattern should I use for import/export?
I have an application where users can set how values are displayed. The users enter a formatting string and the component uses FormatFloat to display the value.
But now we are using a new third-party component which formats values using the Format function and of course none of our user formats work as the Format & FormatFloat functions use a different syntax.
So does anyone know of a way of converting between the two? Or maybe someone has code to do it?
Thanks,
AJ
Though the format strings for FormatFloat can be more or less transformed to ones for Format, you may only get real similarity for positive values. The Format method simply doesn't offer enough flexibility to incorperate the features and fine-grained control that the format strings for the FormatFloat method offers.
For example, the FormatFloat method allows for three different formats for positive, negative and zero values. Also, the FormatFloat format strings allow for string literals, e.g. '#,##0.00;;Zero'; (which means that zero values are printed as "Zero").
To get something similar using the Format function, you yourself would need to do all the grunt work that FormatFloat is doing for you through the format string.
So, although I am as opposed to changing third party control's sources as I am opposed to changing the vcl sources, I am with David on this one: find a way to make the third party control use the FormatFloat function. Preferably through a custom descendant or through an interposer class (also known as an interceptor class), but if that fails, by all means change the third party control's source. Just make sure that you mark the changed sections properly so you can easily redo it when switching to a new version of that control.
Far and away the simplest solution will be to take the source of the 3rd party component (you should only consider using 3rd party Delphi components that come with source) and modify it to call FormatFloat rather than Format.
I have an application that searches files on the computer (configurable path, type etc). Currently it adds information to a database as soon as a matching file is found. Rather than that I want to hold the information in memory for further manipulation before inserting to database. The list may contain a lot of items. I consider performance as important factor. I may need iterating thru the items, so a structure that can be coded easily is another key issue. and how can I achieve php style associative arrays for this job?
If you're using Delphi 2009, you can use a TDictionary. It takes two generic parameters. The first should be a string, for the filename, and the second would be whatever data type you're associating with. It also has three built-in enumerators, one for key-value pairs, one for keys only and one for values only, which makes iterating easy.
Another solution would be to use just a standard TStringList.
As long as it's sorted and has some duplicate setting other than dupAccept, you can use indexof or indexofname to find items in the list quickly.
It also has the Objects addition which allows you to store object information attached to the name. Starting with D2009, TStringList has the OwnsObject property which allows you to delegate object cleanup to the TStringList. Prior to D2009 you have to handle that yourself.
Much of this will depend on how you are going to use the list and to what scale. If you are going to use it as a stack, or queue, then a TList would work fine. If your needing to search through the list for a specific item then you will need something that allows faster retrieval. TDictionary (2009) or TStringList (pre 2009) would be the most likely choice.
Dynamic arrays are also a possiblity, but if you use them you will want to minimize the use of SetLength as each time it is called it will re-allocate memory. TList manages this for you, which is why I suggested using a TList. if you KNOW how many you will deal with in advance, then use a dynamic array, and set its length on the onset.
If you have more items than will fit in memory then your choices also change. At that point I would either use a database table, or a tFileStream to store the records to be processed, then seek to the beginning of the table/stream for processing.
Try using the AVL-Tree by http://sourceforge.net/projects/alcinoe/ as your associative Array. It has an iterate-method for fast iteration. You may need to derive from his baseclass and implement your own comparator, but it's easy to use.
Examples are included.