【问题标题】:Get the name of the object passed in a byref parameter vb.net获取通过byref参数传递的对象名称vb.net
【发布时间】:2011-11-06 09:30:12
【问题描述】:

如何获取通过ref传递给方法的对象的名称?

例子:

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

我正在使用它进行日志记录。我多次使用一种方法,最好记录下我传递给它的变量的名称。既然是byref传的,应该能得到这个名字吧?

对于提供答案的 minitech:

这将为您提供方法中的参数名称及其类型,而不是通过引用传递的变量的名称。

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

如果你把它放在上面的“mymethod”中,你会得到“o”和“Object”。

【问题讨论】:

    标签: vb.net reflection


    【解决方案1】:

    这显然是 Visual Basic 控件处理问题的方式。

    它们有一个基本控件类,除了这些控件可能具有的任何其他公共属性外,它们还有一个名称属性。

    例如: 公共 MustInherit 类 NamedBase 公共名称作为字符串 结束类

    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
    

    中间窗口的输出应该是:

    我的变量名是:x

    【讨论】:

      【解决方案2】:

      如果您的程序相对于生成它的代码仍然在同一个位置,这可能会起作用:

      '  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, "\).*$", "")
      

      您可以使用 depth 参数控制对堆栈跟踪的挖掘深度。 4 适合我的需要。您可能需要使用 1 2 或 3。

      【讨论】:

        【解决方案3】:

        抱歉,这是您的解决方案。我在方法签名中留下了(ByVal o As Object),以防你用它做更多的事情。

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

        您也可以创建一个接口,但这只会允许您将MyMethod 与您设计的类一起使用。您可能可以做更多的改进来改进它,但就这段代码而言,您只能在创建时设置RealName。

        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
        

        【讨论】:

          【解决方案4】:

          或者,您可以使用反射获取对象的“类型”。

          示例:(使用 LinqPad 执行)

          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
          

          【讨论】:

          • 我认为他要求的是变量名,而不是所使用的类的名称
          • 是的,但作为替代解决方案,您可以查看类型是否提供可用于登录的信息。即 DateTime 进来了,然后 Int32 进来了等等。
          • 谢谢,这很有帮助,但我真的在寻找变量名。
          【解决方案5】:

          那是不可能的。变量的名称不存储在 IL 中,只有类成员或命名空间类的名称。通过引用传递它绝对是零差异。你甚至无法让它打印出“o”。

          此外,您为什么要这样做?

          【讨论】:

          • @Hans Passant:“我的对象”?不,这不对。这是一个变量。
          • 用于记录。这是一个无需 GUI 即可运行的过程,我试图不重复代码。如果我能得到变量名,那对日志会很好。我现在只需要将它作为字符串文字传递给我的方法。但“不”也是一个答案。谢谢。请参阅我的问题以获取打印“o”的代码示例(我对其进行了编辑)。
          • 这可以在 PHP 中完成吗?也许这就是我记得拥有那种力量的地方哈哈。
          • @John:我不知道...您可以使用语法$$varname 按变量名使用变量,但我根本不知道有任何编程语言会保留变量名称,甚至不是脚本语言。您仍然可以通过使用更具描述性的名称来避免重复自己,例如 log.WriteLine(String.Format("Found {0} non-user-opened sessions", numSessions))。
          猜你喜欢
          • 2018-07-31
          • 2011-08-21
          • 2019-11-09
          • 2013-02-11
          • 2011-10-23
          • 1970-01-01
          • 1970-01-01
          • 2015-06-06
          • 1970-01-01
          相关资源
          最近更新 更多