Find all Class Helpers in Delphi at runtime using RTTI?
Asked Answered
A

1

5

Does the extended RTTI in Delphi 2010 offer a way to list defined Class and Record Helpers at run time?

As far as I know Delphi does not show a hint or warning when more than one class helper is defined for a class, class helper detection might be a helpful routine in 'quality assurance'.

p.s. of course I know I should never ever use third party components or libraries without source code, which would make it easy to grep class helpers.

Animus answered 10/2, 2010 at 18:45 Comment(4)
It doesn't matter whether more than one helper is defined at run time. If you try to use methods introduced by a helper other than one the most recently defined, your code won't even compile, so there is no run time.Mcgurn
@Rob: quote from the linked page (Turbocharging Delphi 2010): "you can define and associate multiple class helpers with a single class type" - does this mean if I associate multiple class helpers with a single class, the code will not compile anymore?Animus
You can create multiple helpers, but only one will be in effect at a time. Please continue reading the sentence you just quoted: "only zero or one class helper applies in any specific location in source code. The class helper defined in the nearest scope will apply. Class helper scope is determined in the normal Delphi fashion (i.e. right to left in the unit’s uses clause)"Mcgurn
Now I understand your first comment :)Animus
M
9

Since class helpers only apply to a class based on what helper is "closest" in scope, a class simply cannot know that a helper exists. For example, you can create a class helper in your unit to "help" a class from another unit for which you have no source. The class in the other unit has no clue about any helpers. If it did have this knowledge, then it would have to be recompiled to take this into account... which leads to the next issue;

Consider this: You could have a class declared in one common unit that is used by many other units throughout your application. In each of those units you declare a new helper for this common class with different methods and "helper" functions. Since each unit knows nothing about the other units that also declare their own helper, there is, by design, no way to somehow coalesce all the helpers. Now consider that this common unit now lives across a pre-compiled package boundary.

Class helpers are seductive little heathens. They promise fame and fortune, but too often they rain down death and destruction... long after you've given yourself over to their wiles.

For this reason, their introduction into the language solved very specific problems, namely the ability to "appear" to introduce functionality into an existing framework. As long as you adhere the "one helper only" rule, and do not stray from that path, you may emerge relatively unscathed. Regardless, you will need to have the combined intestinal fortitude of Beowulf, Leonidas (of Sparta), and Frodo Baggins to navigate through these waters.

Given that, here on the RAD Studio team, we are loath to ever use a class helper where it can be avoided. And when we do use them, an appropriate phalanx is formed before we even begin...

There be dragons here...

Malkin answered 10/2, 2010 at 19:50 Comment(8)
+1 for the dragons. :-) Well, you should have introduced a new visibility for class helpers called Intestinal and have that reserved for the R&D team and a few Paladins out there on the bleeding edge... <G>Charles
Ya know, I've always sorta wondered why it was implemented that way. Why do class helpers have to be so scary that even the Delphi team is afraid of them? Why are we restricted to using only one on a class at any given time?Sphery
It mainly has to do with the scoping rules of the language. We were not about to break down those rules, as that would have created an even larger chasm of confusion. They're not scary, if and only if, you really, truly understand the rules and the pitfalls thereof. The problems comes in when you are using helpers as an integral part of your framework's API. Then you run the real risk of wrestling with dueling helpers.Malkin
@Mason: Because they were never intended as a general purpose extension to the language!!! They were introduced to solve a very specific problem in the VCL. The documentation has always warned people NOT to use them for more general purposes (and there are alternative techniques that achieve the same AND MORE which are imho better (more opaque) and have always worked in all versions of Delphi!)Shipload
@Deltics: No, there are a few things that only class helpers can do, such as add a method to a base class (and all its descendants) that's able to use that class's protected members. There's no other language feature that can do this AFAIK. Also, if it were implemented properly, it would be a lot more useful. Take a look at LINQ to see the sorts of things that you can accomplish with properly-done class extensions.Sphery
What exactly would "implemented properly" mean? That is a very vague statement. "Make them like C# extension methods" isn't an answer. And, remember, that C# extension methods also have similar scoping rules, and can also get you into just as much trouble. Extension methods are not the only thing that makes LINQ, LINQ. It is the heavy use of type inferencing and and a fluent style API that does that.Malkin
@Mason: You can implement a psuedo class extender to do that. The only difference is that to use that pseudo extender you have to explicitly cast to it. But I see that as a benefit for code maintenance because it makes it entirely obvious that what you are doing is not supported directly by the instance but is using a "trick". With a class "helper" the fact that the method is not directly supported by the instance is obfuscated and with potentially multiple class helpers in existence but only one helper in scope, changing scope can break code in a way that explicit pseudo casts cannot.Shipload
@Mason 2: There is nothing that a class helper can do that alternative techniques cannot do, save for the fact that the "class helper" does it in a less opaque, more transparent, more fragile way and are therefore more dangerous. Introducing class helper "A" - perhaps unknowingly/inadvertently - can break [fail compilation of] previously valid code already using class helper "B" or damage it [if both helpers provide methods with the same name(s) but doing slightly different things].Shipload

© 2022 - 2024 — McMap. All rights reserved.