How to find a property name by programming ?

  • Thread starter Thread starter Gilbert Tordeur
  • Start date Start date
G

Gilbert Tordeur

Hello.

Context : VB2008.

Let's consider a class C1 with a public property P1.

From the code C1.P1 ou similar, I would like to get back the property name:
"P1". For example to set a Listbox DisplayMember, or anything else. So that
if somebody later renames P1 in P2, my DisplayMember automatically becomes
"P2".

I guess I have to use System.Reflection, but it's such a mess that I am
lost.

Thanks for your help,
Gilbert
 
Salut !!!

Even if using reflection how your code will now that this is now P2 that
should be used ?

At some point you have to used named elements. IMO doing so using reflection
to accomodate uninformed changes perhaps doesn't worth ?

Or do you intend to have a particular attribute on those property to know
that this particular property should be used as a display name ? Then you
could use reflection and search for this specific attribute (but again one
could just choose to suppress this attribute and your code wouldn't know
what to do then).

At which point are you stuck ? Try perhaps
http://www.vb-helper.com/howto_net_list_properties.html
 
Bonjour Patrice. During holiday you work in English ?

Look:
Dim o As New MyClass
Dim s As string = o.GetType.ToString

s will contain like "Project.MyClass". From the name MyClass in the code I
can get the string "MyClass".

Now taking my previous example:
Public Class C1
Public ReadOnly Property P1() As String
Get
Return "AZERTY"
EndGet
End Property
etc...
End Class

I want the same : from the name P1 in the code I want to get the string
"P1". By programming I just want to get the name of the P1 property (the
result should be "P1"). That's all.

If you want to know why. First I am curious. Second I want to write flexible
code. And writing some code like
MyListBox.DisplayMember = "P1" gives me buttons. Because if someday somebody
makes a Rename of P1 into something else (P2 for example) by right click -
rename, with «MyListBox.DisplayMember = "P1"» my code will not run
correctly.

With System.Reflection, I have found how to, knowing a property name as a
string ("P1"), I can get the property value P1. But here the property name
is what I am looking for, that's nearly the contrary.

Gilbert
 
Gilbert said:
Bonjour Patrice. During holiday you work in English ?

Look:
Dim o As New MyClass
Dim s As string = o.GetType.ToString

s will contain like "Project.MyClass". From the name MyClass in the
code I can get the string "MyClass".

Now taking my previous example:
Public Class C1
Public ReadOnly Property P1() As String
Get
Return "AZERTY"
EndGet
End Property
etc...
End Class

I want the same : from the name P1 in the code I want to get the
string "P1". By programming I just want to get the name of the P1
property (the result should be "P1"). That's all.

If you want to know why. First I am curious. Second I want to write
flexible code. And writing some code like
MyListBox.DisplayMember = "P1" gives me buttons. Because if someday
somebody makes a Rename of P1 into something else (P2 for example) by
right click - rename, with «MyListBox.DisplayMember = "P1"» my code
will not run correctly.

With System.Reflection, I have found how to, knowing a property name
as a string ("P1"), I can get the property value P1. But here the
property name is what I am looking for, that's nearly the contrary.

Gilbert

As Patrice said, somewhere you must refer to the property. If you change the
name, you will have to change the reference.

Referring to "I want the same": The difference
between getting the name of the type of the object is that the object is an
object while the property is not. There is no "property object" of which you
can call a member reflecting the property. A property does not exist in
memory the same way like an object does. A property is code while an object
is data. Is it understandable what I say? Therefore, something like
"myclass.p1.propertyname" is neither possible nor makes sense.
(Though, it's not impossible that an additional VB keyword introduced in the
future will do the same with type members like GetType currently does with
types: GetMember(C1.P1). Currently this does not exist. Anyway, you'd have
to change the reference to P1 here too if it's renamed, so it wouldn't
change anything.)

You _can_ refer to the property but you must put "P1" (inside quotes)
somewhere to be able to get the reflection
information:

Dim propinfo = GetType(C1).GetProperty("P1")

Maybe this helps if you had to write "P1" multiple times, before, and now
you can just refer to variable propinfo, but otherwise not. In addition,
you'll probably name the variable "PropInfoP1" but then you will have to
change it to "PropInfoP2" later anyway. So, there's no way around.


Armin
 
Gilbert said:
Let's consider a class C1 with a public property P1.

From the code C1.P1 ou similar, I would like to get back the property
name: "P1". For example to set a Listbox DisplayMember, or anything
else. So that if somebody later renames P1 in P2, my DisplayMember
automatically becomes "P2".

If someone is going to start renaming things in your program, surely that is
their look-out? What if they decided that they wanted P1 to be an integer
instead of a string - do you want your program to be able to cope with that
too?

Andrew
 
You haven't responded to the main point that Patrice made:

How are you going to identify the property that you want to get the name of?
You can't use the property name, because that might have changed (if I
understand your description properly). If you can answer that question
then you are on the way to solving your problem. Patrice mentioned
searching by an attribute. If you can nominate the attribute and the value
that you expect it to be, then perhaps someone here can show you how to
search properties. For instance, is the property you are interested in the
only one in the class of a particular type? Enumerating the properties of
the class is not difficult - selecting the one that you need to return the
name for is the only tricky bit, and to do that you need to decide how you
will identify it in the list of enumerated properties.

The PropertyInfo class and Type.GetProperties will give you the enumeration.
You have to provide the rule that identifies the one you are interested in.
 
Thank you to everyone' contribution to this problem.

Thanks to Éric contribution (on the French forum), here is a (short) example
of how to do, using MethodBase.GetCurrentMethod.Name:

My class
:
Imports System.Reflection

Public Class CjcCustomer
Private CustomerIDPropertyName As String
Private CustomerNamePropertyName As String
Private m_CustomerID As Integer
Private m_CustomerName As String

Public Property CustomerName() As String
Get
If String.IsNullOrEmpty(CustomerNamePropertyName) Then
CustomerNamePropertyName =
MethodBase.GetCurrentMethod.Name.Substring(4)
End If
Return m_CustomerName
End Get
Set...
End Property

Public Property CustomerID() As Integer
Get
If String.IsNullOrEmpty(CustomerIDPropertyName) Then
CustomerIDPropertyName =
MethodBase.GetCurrentMethod.Name.Substring(4)
End If
Return m_CustomerID
End Get
Set...
End Property

Public Sub New()
Dim x1 = Me.CustomerName ' to fill CustomerNamePropertyName
Dim x2 = Me.CustomerID ' to fill CustomerIDPropertyName
End Sub

Public Function GetDisplayName() As String
Return CustomerNamePropertyName
End Function

Public Function GetValueName() As String
Return CustomerIDPropertyName
End Function
End Class

My code to display a ListBox :

' Let's assume LstClient As List(Of CjcCustomer), which contains at least
one item

MaListBox.DisplayMember = LstClient(0).GetDisplayName
MaListBox.ValueMember = LstClient(0).GetValueName
MaListBox.DataSource = LstClient

Gilbert
 
Gilbert said:
Thank you to everyone' contribution to this problem.

Thanks to Éric contribution (on the French forum), here is a (short)
example of how to do, using MethodBase.GetCurrentMethod.Name:

My class
Imports System.Reflection

Public Class CjcCustomer
Private CustomerIDPropertyName As String
Private CustomerNamePropertyName As String
Private m_CustomerID As Integer
Private m_CustomerName As String

Public Property CustomerName() As String
Get
If String.IsNullOrEmpty(CustomerNamePropertyName) Then
CustomerNamePropertyName =
MethodBase.GetCurrentMethod.Name.Substring(4)
End If
Return m_CustomerName
End Get
Set...
End Property

Public Property CustomerID() As Integer
Get
If String.IsNullOrEmpty(CustomerIDPropertyName) Then
CustomerIDPropertyName =
MethodBase.GetCurrentMethod.Name.Substring(4)
End If
Return m_CustomerID
End Get
Set...
End Property

Public Sub New()
Dim x1 = Me.CustomerName ' to fill CustomerNamePropertyName
Dim x2 = Me.CustomerID ' to fill CustomerIDPropertyName
End Sub

Public Function GetDisplayName() As String
Return CustomerNamePropertyName
End Function

Public Function GetValueName() As String
Return CustomerIDPropertyName
End Function
End Class

My code to display a ListBox :

' Let's assume LstClient As List(Of CjcCustomer), which contains at
least one item

MaListBox.DisplayMember = LstClient(0).GetDisplayName
MaListBox.ValueMember = LstClient(0).GetValueName
MaListBox.DataSource = LstClient

Gilbert


What the... is this? I've rarely seen such a, well, 'special' approach. What
do yo do if you haven't accessed the property before? It would fail. What if
you change the Function name? You'd have the same problem like when you
rename the proeprty. What if there are more properties and consequently
property names? How do you distinguish between them? What if the property
names and (consequently) their corresponding GetXYDisplayName change?


Armin
 
Armin,

Thank you for your comments.

1. I am interested in the way how to retrieve a property name, whatever
application one can do with that.

2. The example is just a piece of code to show how to use
MethodBase.GetCurrentMethod.Name. It does not have the pretention to be a
perfect program.

3. "What do yo do if you haven't accessed the property before?". Good
remark. That's why the property is accessed by the Sub New, so it does not
matter.

4. "What if you change the Function name?" Which Function name? There is no
Function in my example.

5. "What if there are more properties and consequently property names?" If
you need so you just create as many methods as you need. My example uses two
methods for two properties.

6. "How do you distinguish between them?" By the method name.

7. "What if the property names and (consequently) their corresponding
GetXYDisplayName change?" If you correctly rename the property by rigth
click / rename then you do not get any problem, the program still works as
before. I do not agree on "and (consequently) their corresponding
GetXYDisplayName", it does not change. But it would be nice to change it
also to keep a better meaning in the name, that's true.

8. Anyway, what if you work "normally", and you write like this ?
MaListBox.DisplayMember = "CustomerName"
MaListBox.ValueMember = "CustomerID"
MaListBox.DataSource = LstClient

Then you can be sure that if you rename a property, you get no compile flag
but your program works differently !

Gilbert
 
Gilbert said:
Armin,

Thank you for your comments.

1. I am interested in the way how to retrieve a property name,
whatever application one can do with that.

If you look at your source code you also know the property name. It does not
change while the application runs.
(yes, know that's not the point)
2. The example is just a piece of code to show how to use
MethodBase.GetCurrentMethod.Name. It does not have the pretention to
be a perfect program.

We would have been able to tell you how to get the name of the _current_
method by creating a Stackframe/trace, but your questions sounded as if you
wanted to refer to the property _outside_ the property.
3. "What do yo do if you haven't accessed the property before?". Good
remark. That's why the property is accessed by the Sub New, so it
does not matter.

Oh, well, then it's a good solution - not.
4. "What if you change the Function name?" Which Function name? There
is no Function in my example.

Public Function GetDisplayName() As String
5. "What if there are more properties and consequently property
names?" If you need so you just create as many methods as you need.
My example uses two methods for two properties.

6. "How do you distinguish between them?" By the method name.

7. "What if the property names and (consequently) their corresponding
GetXYDisplayName change?" If you correctly rename the property by
rigth click / rename then you do not get any problem, the program
still works as before. I do not agree on "and (consequently) their
corresponding GetXYDisplayName", it does not change. But it would be
nice to change it also to keep a better meaning in the name, that's
true.

I asked the questions to lead you to the fact that multiple properties
require multiple, differently named functions that should have appropriate
names to indicate which property they are related to. The consequence is
that, if you you rename a property, you have to rename the function
returning the names of their corresponding properties.

8. Anyway, what if you work "normally", and you write like this ?
MaListBox.DisplayMember = "CustomerName"
MaListBox.ValueMember = "CustomerID"
MaListBox.DataSource = LstClient

Then you can be sure that if you rename a property, you get no
compile flag but your program works differently !

Yes, much better than calling each property inside the constructor just to
be able to get the stackframe in order to get the name of a property. This
is one of the most bizarre scenarios of abuse of reflection I've ever seen.
IMHO, this is unacceptable because a property is called because you want to
get/set it. What if you don't want to make the property really work but just
want to initialize the field holding the property name?


What you are doing reminds me of a "programming technique" I came across
several years ago (in VB6): A method had static local variables. The method
had an additional Boolean argument. If the argument was True, the only thing
the method did was setting the static variables to Nothing (because there
was no other way to do this from outside). You may call it a solution but I
call it a hack. The problem was that the approach was wrong. However, I'm
not able to explain what's wrong or right.


Armin
 
Back
Top