John
John

Reputation: 2802

Get the name of the object passed in a byref parameter vb.net

How can I get the name of the object that was passed byref into a method?

Example:

Dim myobject as object

sub mymethod(byref o as object)
    debug.print(o.[RealName!!!!])
end sub

sub main()
    mymethod(myobject)
    'outputs "myobject" NOT "o"
end sub

I'm using this for logging. I use one method multiple times and it would be nice to log the name of the variable that I passed to it. Since I'm passing it byref, I should be able to get this name, right?

For minitech who provided the answer:

This would give you the parameter name in the method and it's type, but not the name of the variable that was passed byref.

using system.reflection

Dim mb As MethodBase = MethodInfo.GetCurrentMethod()
For Each pi As ParameterInfo In mb.GetParameters()
    Debug.Print("Parameter: Type={0}, Name={1}", pi.ParameterType, pi.Name)
Next

If you put that in "mymethod" above you'd get "o" and "Object".

Upvotes: 0

Views: 5774

Answers (5)

JBStCyr
JBStCyr

Reputation: 11

This is the apparently how Visual Basic controls handle the problem.

They have a base control class that in addition to any other common properties these controls may have has a name property.

For Example: Public MustInherit Class NamedBase Public name As String End Class

Public Class MyNamedType
    Inherits NamedBase
    public Value1 as string
    public Value2 as Integer
End Class

dim x as New MyNamedType

x.name = "x"
x.Value1 = "Hello, This variable is name 'x'."
x.Value2 = 75

MySubroutine(x)

public sub MySubroutine(y as MyNamedType)
    debug.print("My variable's name is: " & y.name)
end sub

The output in the intermediate window should be:

My variable's name is: x

Upvotes: 0

jonrgrover
jonrgrover

Reputation: 1

If your program is still in the same place relative to the code that made it, this may work:

'  First get the Stack Trace, depth is how far up the calling tree you want to go
Dim stackTrace As String = Environment.StackTrace
Dim depth As Integer = 4

'  Next parse out the location of the code
Dim delim As Char() = {vbCr, vbLf}
Dim traceLine As String() = stackTrace.Split(delim, StringSplitOptions.RemoveEmptyEntries)
Dim filePath As String = Regex.Replace(traceLine(depth), "^[^)]+\) in ", "")
filePath = Regex.Replace(filePath, ":line [0-9]+$", "")
Dim lineNumber As String = Regex.Replace(traceLine(depth), "^.*:line ", "")

'  Now read the file
Dim program As String = __.GetStringFromFile(filePath, "")

'  Next parse out the line from the class file
Dim codeLine As String() = program.Split(delim)
Dim originLine As String = codeLine(lineNumber * 2 - 2)

'  Now get the name of the method doing the calling, it will be one level shallower
Dim methodLine As String = Regex.Replace(traceLine(depth - 1), "^   at ", "")
Dim methodName = Regex.Replace(methodLine, "\(.*\).*$", "")
methodName = Regex.Replace(methodName, "^.*\.", "")

'  And parse out the variables from the method
Dim variables As String = Regex.Replace(originLine, "^.*" & methodName & "\(", "")
variables = Regex.Replace(variables, "\).*$", "")

You control the depth that this digs into the stack trace with the depth parameter. 4 works for my needs. You might need to use a 1 2 or 3.

Upvotes: 0

Hand-E-Food
Hand-E-Food

Reputation: 12814

Sorry to say, but this is your solution. I left (ByVal o As Object) in the method signature in case you're doing more with it.

Sub MyMethod(ByVal o As Object, ByVal name As String)
    Debug.Print(name)
End Sub

Sub Main()
   MyMethod(MyObject, "MyObject")
End Sub

Alternatively you could create an interface, but this would only allow you to use MyMethod with classes you design. You can probably do more to improve it, but as this code stands you can only set the RealName at creation.

Interface INamedObject
    Public ReadOnly Property RealName As String
End Interface

Class MyClass
    Implements INamedObject

    Public Sub New(ByVal RealName As String)
        _RealName = RealName
    End Sub

    Private ReadOnly Property RealName As String Implements INamedObject.RealName
        Get
            Return _RealName
        End Get
    End Property
    Private _RealName As String
End Class

Module Main
    Sub MyMethod(ByVal o As INamedObject)
        Debug.Print(o.RealName)
    End Sub

    Sub Main()
        Dim MyObject As New MyClass("MyObject")
        MyMethod(MyObject)
    End Sub
End Module

Upvotes: 0

Jeremy
Jeremy

Reputation: 3951

Alternatively you could get the 'Type' of the object using reflection.

Example: (Use LinqPad to execute)

Sub Main    
  Dim myDate As DateTime =  DateTime.Now
  MyMethod(myDate)

  Dim something As New Something
  MyMethod(something)       
End Sub

Public Class Something
   Public Sub New
    Me.MyProperty = "Hello"
   End Sub
   Public Property MyProperty As String
End Class

Sub MyMethod(Byref o As Object)
   o.GetType().Name.Dump()
End Sub

Upvotes: 1

Ry-
Ry-

Reputation: 225125

That's impossible. Names of variables are not stored in IL, only names of class members or namespace classes. Passing it by reference makes absolutely zero difference. You wouldn't even be able to get it to print out "o".

Besides, why would you ever want to do that?

Upvotes: 3

Related Questions