VB.net - accessing the data fields of a class

blahblah99

Platinum Member
Oct 10, 2000
2,689
0
0
I'm not a vb.net programmer but I have a small task to do that's giving me some problems and was wondering if anyone can provide some help.

I have a class that retrieves data from a database. The data gets stored in the class's data fields, but they are not exposed. Adding the class to a watch list shows the data fields, but they aren't accessible.

Is there any way to retrieve the data field by using some tricks?

For example, the code goes something like:

Dim obj as widget
Dim color as string

color = obj.Foreground 'invalid and will not compile because Foreground isn't available.

However, if obj is added to the watch list, Foreground will show up and contains "Red"


Edit: Forgot to mention that the class is part of a compiled DLL, which I don't have source code to so I can't just make the data field public.
 

nickbits

Diamond Member
Mar 10, 2008
4,122
1
81
You could try to get the value using reflection but it probably won't work. You really need to change the obj source code.
 

jthg

Member
Nov 11, 2003
100
0
71
Just to start with a disclaimer: private fields are usually private for a good reason. At the very least, it's an indication that the maker of the class reserves the right to change the field on a whim and expect that the change will have no effect on anything outside of the class. Plus, using the following hack to to get at private fields will look ugly to other people who read your code. Put in some comments to explain why it's necessary.

Sorry the following is in C#. I've pretty much forgotten VB.Net syntax and I don't have any VB.Net IDE on hand right now.

 

jthg

Member
Nov 11, 2003
100
0
71
Well that doesn't look too readable. This should be at least passable:

using System;
using System.Reflection;

class Program {
public class SomeClass {
/// <summary>
/// A private field
/// </summary>
private string _value = "looks like it works";

/// <summary>
/// A private property
/// </summary>
private string Value {
get {
return _value;
}
set {
_value = value;
}
}
}

static void Main(string[] args) {
// Instantiate an object which we're going to inspect later via reflection
object obj = new SomeClass();
// Get the type of the object
Type type = obj.GetType();

// Get information about the private field we're interested in
FieldInfo fi = type.GetField("_value", BindingFlags.NonPublic | BindingFlags.Instance);
// Use reflection to retrieve the value
string fieldValue = fi.GetValue(obj) as string;
// Print value to command line
Console.WriteLine(fieldValue);

// Get information about the private property we're interested in
PropertyInfo pi = type.GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance);
// Use reflection to retrieve the value
string propValue = pi.GetValue(obj, null) as string;
// Print value to command line
Console.WriteLine(propValue);
}
}
 

blahblah99

Platinum Member
Oct 10, 2000
2,689
0
0
Originally posted by: jthg
Well that doesn't look too readable. This should be at least passable:

using System;
using System.Reflection;

class Program {
public class SomeClass {
/// <summary>
/// A private field
/// </summary>
private string _value = "looks like it works";

/// <summary>
/// A private property
/// </summary>
private string Value {
get {
return _value;
}
set {
_value = value;
}
}
}

static void Main(string[] args) {
// Instantiate an object which we're going to inspect later via reflection
object obj = new SomeClass();
// Get the type of the object
Type type = obj.GetType();

// Get information about the private field we're interested in
FieldInfo fi = type.GetField("_value", BindingFlags.NonPublic | BindingFlags.Instance);
// Use reflection to retrieve the value
string fieldValue = fi.GetValue(obj) as string;
// Print value to command line
Console.WriteLine(fieldValue);

// Get information about the private property we're interested in
PropertyInfo pi = type.GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance);
// Use reflection to retrieve the value
string propValue = pi.GetValue(obj, null) as string;
// Print value to command line
Console.WriteLine(propValue);
}
}

Thanks, that's precisely the info I needed to get going!

The private field that I am trying to access is strictly for read purposes, which the original coders might have forgotten to expose.
 

jthg

Member
Nov 11, 2003
100
0
71
I should mention that accessing fields using reflection is a couple hundred times slower than reading a (public) field directly. If you really need it to be faster, there is another way to do it which has no performance penalty, but involves generating CIL at runtime.
 

PhatoseAlpha

Platinum Member
Apr 10, 2005
2,131
21
81
If the class isn't sealed and the parts are protected instead of just private, perhaps you can make your own class that inherits from the base class, and expose it there.