Using reflection on collections w/in objects

E

Eric Goforth

Hello,

I have a generic subroutine that I pass an object and
fieldname as arguments. The subroutine then uses
reflection to search for the value of the fieldname.

For example:

'Calling the Sub
GetObjectValue(objMyCustomer, "Address.Zip")

'The definition of the Sub
Public Shared GetObjectValue(MyObj as Object, FieldName As
String)

Dim Field As FieldInfo
Dim colObject As Object


If FieldName.IndexOf(".") > 0 Then
Do While strTemp.IndexOf(".") > 0
Field = colObject.GetType.GetField(Left(strTemp, _
strTemp.IndexOf(".")))
If Field Is Nothing Then Return Nothing
strTemp = Mid(strTemp, strTemp.IndexOf(".") + 2, _
Len(strTemp) - strTemp.IndexOf("."))
colObject = Field.GetValue(colObject)
Loop

'A bunch of other junk goes here

End Sub

The logic works, there's a problem when what you're trying
to look for is in a collection. For instance, if I have
collection of Addresses, like home address, mailing
address, work address, etc.

I want to get the Zip code of, say, the work address.
When I call it, GetType.GetField successfully assigns
Field as a {System.Reflection.RuntimeFieldInfo}. I don't
see a way to test for Field (actually Address) being a
collection. Try to do a Ctype and then test for not
returning that particular error code?

I'd then like loop through my collection and return the
zip code for a particular element, like Address(1).Zip.

The reason I'm going to all this trouble is that I want
the piece that calls GetObjectValue not to have to know
what the type of object that it's working with. I just
give him an object and he parses through it looking for
fields in an XML document that is passed to him as well.

-Eric
 
L

Laxa

hello,

dim myCollection as object
dim myItem as object
dim myMethodInfo as MethodInfo

myMethodInfo = myCollection.gettype.GetMethod("Item")

if not myMethodInfo is nothing then

myItem = myMethodInfo.Invoke(myCollection ,new object() {MyIndex})
.......

Pascal
 
E

Eric Goforth

Public Shared Function GetObjectProperty(ByVal CurrObject As Object,
ByVal FieldName As String) As Object

Dim memInfo As MemberInfo()
Dim colInfo As MemberInfo()
Dim Field As FieldInfo
Dim colField As FieldInfo
Dim colProp As PropertyInfo
Dim colObject As Object
Dim strTemp As String = ""
Dim myObj As Object
Dim myMethodInfo As MethodInfo
Dim myItem As Object

strTemp = FieldName
colObject = CurrObject

'Test to see if FieldName is for a sub
'object ie. Customer.Name
If FieldName.IndexOf(".") > 0 Then
Do While strTemp.IndexOf(".") > 0
If strTemp.IndexOf("(") < strTemp.IndexOf(".") Then
'Object is a collection
'e.g. "Products(0).Name"
Field = colObject.GetType.GetField
(strTemp.Substring(0, strTemp.IndexOf("(")))
colObject = Field.GetValue(colObject)

'At this point colObject is my Collection Object

'If I do the following, myMethodInfo is Nothing
myMethodInfo = colObject.gettype.GetMethod("Item")

'Same happens here
myMethodInfo = colObject.gettype.GetMethod("Item(0)")



'At this point colObject.GetType.GetMember("Item(0)") will
return
'System.Reflection.MemberInfo(), but it only appears to
contain information
'about the structure of the data, not the data itself



'I can see the colObject.Item(0).Name, etc in the watch pane,
but am not allowed
'to set colObject, option strict prohibits late binding
'colObject = colObject.Item(0)


Else
'Object is a NOT a collection
'...
End If
Loop



hello,

dim myCollection as object
dim myItem as object
dim myMethodInfo as MethodInfo

myMethodInfo = myCollection.gettype.GetMethod("Item")

if not myMethodInfo is nothing then

myItem = myMethodInfo.Invoke(myCollection ,new object() {MyIndex})
.......

Pascal
 
C

CJ Taylor

This is kind of a f***ed up way to go about this. You may want to use more
of the reflection namespace to your advantage and see if an object inherits
"CollectionBase" or if it interfaces something like ICollection, IList, or
IEnumerable

Screw string parsing.. =)

CJ
 
E

Eric Goforth

Hello,

It is a little clunky, but there is a reason for it. I have VB6 Adobe
interface. I'd have written it in VB.Net, but .NET doesn't support DDE
very well and OLE doesn't work with the free Acrobat Reader.

At any rate this Adobe interface takes an xml string and a file path,
parses the xml and plugs the xml fields into the fields on the Adobe
Acrobat template.

I have a document class that can be either a .pdf file or other document
format. Each document object is associated with an object in my
application. If it's a .pdf file I instantiate it with an object and a
dataset. The dataset contains the mapping from object property name ==>
field name in my Adobe template.

The document looks at the object you've given it and looks up the values
in the object that are associated with the .pdf field names. It then
builds the xml to pass down to the Adobe interface when it's time to
print or view the document.

So the point is that the whole thing is supposed to be table-driven,
which is why I have stuff like Customers(1).Name, so I can store it in
my table. I can add documents and field mappings in my object and have
them print as needed.

-Eric

CJ wrote:

This is kind of a f***ed up way to go about this. You may want to use
more
of the reflection namespace to your advantage and see if an object
inherits
"CollectionBase" or if it interfaces something like ICollection, IList,
or
IEnumerable

Screw string parsing.. =)

CJ
 
L

Laxa

Oups, sorry for the wrong GetMethod for a property :-(

I agree with CJ Taylor, check if the object implements ICollection,
IList, IEnumerable interface (FindInterfaces, GetInterface...) and
cast or use InvokeMember

MyItem = MyCollection.GetTYpe.InvokeMember("Item",
BindingsFlags.GetProperty, Nothing,MyCollection, New Object()
{MyIndex})


Pascal
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top