How can I check an interface property's visibility? - delphi

I have started writing web services in Delphi 2010 and am unit testing to make sure they function as planned. My unit tests of the code passed but one web service method didn’t return a value when called as a service (i.e. through SoapUI). After many hours of searching through the code I discovered it was because the properties on my return object weren’t in the published section of the interface; they were in the public section.
Is there a way for my unit tests to check variable visibility on objects so I can avoid this problem in the future? I was trying to find a way with RTTI but haven’t been able to find anything.

You can determine whether a property was declared published by attempting to access that property's RTTI. A public property has no RTTI, a published property does.
Something like this:
if (GetPropInfo(myobject, "PropertyName") != null) then
// it's published...
For more info on RTTI, see Brian Long's article: http://www.blong.com/Conferences/BorConUK98/DelphiRTTI/CB140.htm

You can do it with RTTI easily enough. You can use the classic RTTI function GetPropInfo in the TypInfo unit. If it returns nil, then no published property by that name exists. Or you can look it up with extended RTTI and check the Visibility property, which will tell you what visibility level it's declared at.

Related

How to get a method param name array/list in Delphi?

Is there any way to get the names of the parameters of a given method of a class/object in an array/delimited string in Delphi 7? Somehow like this:
var
s : string;
aSL : TStringList;
begin
...
// using rtti calls in TMethodUtility.collectParamNames
s := TMethodUtility.collectParamNames( TStringList.addObject );
// or
TMethodUtility.collectParamNames( TStringList.addObject, aSL );
...
end;
Thanks in advance!
It is technically possible (otherwise the IDE's Form Designer could not generate code for component event handlers at design-time), however, there are important caveats that will hinder your goal (and make the particular example in your question impossible to resolve):
the necessary RTTI is only generated for properties that are declared as published (such as component events). RTTI is not generated for methods themselves (even published ones), or for properties that are not published.
TObject has a public MethodAddress() method for getting the memory address of a published method (the DFM streaming system uses this when hooking up event handlers), however you cannot get the necessary RTTI from a method pointer alone.
IF you can match a given method pointer to the value of a published event, then you can extract the parameter names from the event's RTTI. Obtain a TypInfo.PPropInfo pointer for the event using the TypInfo.GetPropInfo() function, then pass its PropType field value to the TypInfo.GetTypeData() function to get a TypInfo.PTypeData pointer, and then you can iterate through its ParamList field (which is an array of records containing ParamName and TypeName fields).
See the following blog article on this topic for more details:
Getting the parameters of published methods.
For what you are attempting, a general-purpose solution would require Extended RTTI that was introduced in Delphi 2010 and thus is not available in Delphi 7. Extended RTTI is not limited to published items, and is much more detailed than what the old-style RTTI provides.

Can we use RTTI to find functions/procedures by name and run them?

As we can find a Property or an Object using RTTI, can we search for a certain function or procedure (not from an object as a method but from an unit) loaded in memory knowing just it's name?
And if we can, is it possible to execute it sending it's parameters?
Delphi's RTTI system is based around types. However, procedures and functions with unit scope are not associated with types and so cannot be reached using RTTI.

Class Reference as Property

Google is useless for these sorts of searches, because you get hundreds of millions of results absolutely none of which relate to the specific question.
The question is simply this:
Is it possible to have a Class Reference Property in Delphi?
If so, how?
Here's what I've tried...
type
TMyObject = class
// ...
end;
TMyObjectClass = class of TMyObject
TMyObjectA = class(TMyObject)
// specifics here
end;
TMyObjectB =class(TMyObject)
// specifics here
end;
TMyComponent = class(TComponent)
private
FObjectType: TMyObjectClass;
published
property ObjectType: TMyObjectClass read FObjectType write FObjectType;
end;
The above code compiles fine, however the Object Inspector does not show the ObjectType property at all.
My objective here (if you haven't already guessed) is to make it so that I can select a class descendant from a specific base class, to make the same component behave in a different way.
I want to do it this way so that the component doesn't need to know about the sub-classes directly (it needs to be fully modular).
Let me just make this bit clear: I cannot use an Enum to choose between the sub-class types as the component cannot directly link to the sub-class types (It's simply not possible in this particular case)
Anyway... thanks in advance!
You can find all classes that descend from a particular base class: Delphi: At runtime find classes that descend from a given base class? and make this a special property with list of values using TPropertyEditor.
If you were going to do this then you would need to provide a property editor. The IDE does not come with property editors for class type properties. You would also need to handle .dfm persistence. You would write the class type out to the .dfm file as a string and when the .dfm file is read, you would need to fixup the reference. New style RTTI could do that.
However, I don't think any of this is actually viable for the following reason. Your design time code runs in a package inside the IDE and does not have access to the class types in the active project in the IDE. Those class types only exist when that project runs. So the ObjectType property in the code in your question cannot be assigned to anything meaningful in the design time package. Well, you could use it for classes defined in the VCL and any other packages installed in your IDE but I rather imagine you'd want to use it on classes defined in the active project.
I think all this means that you should instead use a simple string property and fixup the class type references only at runtime.

How do I determine the type of the implementing object of an interface

I'm attempting to write a unit test for a simple factory class that creates one of several possible implementing objects and returns it as an interface reference.
DUnit has a built in procedure, CheckIs(AObject: TObject; AClass: TClass; msg: string), that based on its name and the parameters it accepts should fail the test if the object's class type doesn't match the expected one. The only problem is it requires an object reference not an interface reference.
So I'm trying to use CheckTrue and perform the comparison in the body of the test but I'm not as familiar with Delphi's type checking support as I am with C#'s.
I know the is operator is out of the question since it only works with object references.
CheckTrue(LMyInterfaceReference {comparison here} TMyClass);
Any suggestions?
BTW, I'm using Delphi 2009 so I don't have access to the new RTTI support added in 2010+.
I'm wondering why you MUST have to test this... maybe you really don't have to.
But if knowing the underlying object of a Interface is a must, you have two choices:
Add a method to the interface which returns the underlying object, just a TObject, and implement this in each class just by returning self.
Hack a bit, for example using this Interface to object routine.
If you don't like hacks and don't feel like upgrading to Delphi 2010+ you may use an interface like this:
IImplementingObjectInterface = interface
function GetImplementingObject: TObject;
end;
Make sure your objects also implement this interface and use it to extract the implementing object. If you need to do this for a lot of objects you can define your own TInterfacedObject derivate that already implements this so you can simply change your inheritance and be done.
Barry Kelly (one of the main Embarcadero Delphi Compiler Engineers) wrote a nice An ugly alternative to interface to object casting this week.
It answers your question.
The fun is that Hallvard Vassbotn wrote a very similar piece of code back in 2004.
From Delphi 2010 on, you can just use an is check or as cast to go back from interface references to object references.
--jeroen

What's the difference between public and published class members in Delphi?

Please could someone explain me what's the difference between public and published class members in Delphi?
I tried to look at Delphi help and I understand that these members have the same visibility, but I don't understand very well how they differ and when should I use published members instead of public ones.
Thanks a lot.
The compiler generates RTTI (Run-Time Type Information) metadata for published members, but not for public members (by default). The main effect of this is that the published properties of an object will appear in the Object Inspector at design time.
I do not know if you are writing components, but if you do, you probably know that properties and events are normally published, so that they can be set using the Object Inspector.
Public
public
property MyProperty: integer read FMyProperty write FMyProperty
MyProperty will not be visible in the Object Inspector.
Published
published
property MyProperty: integer read FMyProperty write FMyProperty
MyProperty will be visible in the Object Inspector.
Public properties and published properties have the same visibility, as you already stated. Published properties are included in RTTI, public properties aren't.
As a side note, there is another special thing with published:
The default visibility of class members is published, so check for unsafe code like:
TTopSecret = class(TObject)
Name: string;
Password: string;
function DecryptPassword(const AValue): string;
public
constructor Create(const AName, AEncryptedPassword: string);
end;
Name, Password and DecryptPassword() are visible 'world-wide'.
Published properties will export Runtime Type Information (RTTI).
Have a look here about RTTI in Delphi
It seems there are lots of good answers already, pointing out the Object INspector, RTTI,
etc. These are all pieces of the puzzle.
If you take away the published keyword, the entire Delphi RAD tool design would require some way to specify which properties are stored in a DFM, inspected in the component property inspector, and can be reloaded at runtime from a DFM when the form or data module is created.
This, in a word, is what Published is for. It is interesting to me that the designers of QT (originally TrollTech, later part of Nokia, later still spun off to Digia) had to emulate this level of RTTI for their C++ RAD library "QT", adding a "published" equivalent and a "property" equivalent, while pure C++ still lacks this fundamental facility.
Runtime Type Informations (RTTI) are only generated for published class members.
At run-time, entries in the published and public sections are equally accessible.
The principal difference between them is that published items of a component appear in the Object Inspector at design-time.
This happens because, for fields in published section RTTI is automatically generated.
The Object Inspector picks this up and uses it to identify what to add to its list of properties and events.
In addition to the other answers:
Published properties are automatically stored by the streaming system.
For instance if you have a TComponent's descendant instance and write it to a TStream with WriteComponent, all (well, not all, but that is another question) published properties are written to the stream without any further coding.
Of course, the streaming system only can do that because the RTTI is available for those published properties.

Resources