I am trying to write something like a key value coding mechanism for objects, where I can call computed properties by name strings. So instead of calling a property “act” of an object “foo”
result = foo.act
I would would be able to call a general getter method with the name of the method as parameter dynamically (instead of “act” as a literal I would use a string variable instead):
result = foo.getValue(“act”)
With the Introspection system as far as I know I can’t call the properties by name but by position in the property array:
myProperties = Introspection.GetType(self).GetProperties
result = myProperties(idx).Value(self)
Since I wouldn’t like to cycle through all Properties and check for the right name I setup a dictionary once at application start for every class which resolves the names of my properties to the position in the Introspection system. I stored this dictionary in the class as a shared property so it is accessable by all instants.
So far so good. Now I want this functionality for different objects by subclassing. Those subclasses should be able to use the “getValue” method by inheritance. The problem is that my dictionary which looks up the positions of the properties in the individual subclasses is shared over all the subclasses since it is a shared property of the base class.
So is there any way to store shared values in a subclass without overriding the shared property of the base class?
If not, another approach would be to have templates of the subclasses which have already implemented the overridden property.
Function getValue(extends obj As Object, propertyName As String) As Variant
if classesDict is nil then classesDict = new Dictionary
dim ti As Introspection.TypeInfo = Introspection.GetType(obj)
dim propDict As Dictionary = classesDict.Lookup(ti, nil)
if propDict is nil then //class not loaded, create propDict and add
propDict = new Dictionary
dim props() As Introspection.PropertyInfo = ti.GetProperties
for i As integer = 0 to props.Ubound
propDict.Value(props(i).Name) = props(i)
next
classesDict.Value(ti) = propDict
end
dim prop As Introspection.PropertyInfo = propDict.Lookup(propertyName, nil)
if prop is nil then
return nil
else
return prop.Value(obj)
end
End Function
End Module[/code]
Or just fold it into your super classes.
You can also use Operator_Subscript on classes to have it read like…
Oh, to fold it into your class: make classesDict Shared but getValue as a regular instance method. Then remove obj from the parameters and change the other occurrences to self.
Basically it’s what you’re doing except the shared dictionary first keys by typeinfo into dictionaries of the propertyinfos, then by name to the individual propertyinfo (no need for an index).