.net 通过反射访问变量

.net 通过反射访问变量,.net,vb.net,variables,reflection,reference,.net,Vb.net,Variables,Reflection,Reference,我有一个用VB.NET编写的Windows窗体解决方案。使用模块MOD1的反射,我希望获取/设置模块MOD2的公共变量。一个强大的约束是只使用字符串,就像命令行解释器所做的那样。下面是我用来重新创建失败环境的代码 在访问简单变量(useDialog)时,此代码的行为与预期一致,但在访问复杂变量(fWin或MainForm)时会出现一些问题。我犯了一些错误,但我不知道是哪一个 请注意:fWin是一个Windows窗体类 Public Class fWin Public BoolValue

我有一个用VB.NET编写的Windows窗体解决方案。使用模块MOD1的反射,我希望获取/设置模块MOD2的公共变量。一个强大的约束是只使用字符串,就像命令行解释器所做的那样。下面是我用来重新创建失败环境的代码

在访问简单变量(useDialog)时,此代码的行为与预期一致,但在访问复杂变量(fWin或MainForm)时会出现一些问题。我犯了一些错误,但我不知道是哪一个

请注意:fWin是一个Windows窗体类

Public Class fWin
    Public BoolValue As Boolean = True
    Public FileRoot As String = ""

    Private Sub fWin_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        mod1.MainForm = Me
        FileRoot = "My file root"
        mod2.Change()
    End Sub
End Class

Module mod1
    Public useDialog As Boolean
    Public PathRoot As String = "My path root"
    Public MainForm As fWin
End Module

Imports System.Reflection
Module mod2
    Dim currAssembly As Assembly = Assembly.GetExecutingAssembly()

    Public Function MemberSearch(memPathName As String, ByRef oParents() As Object) As Boolean
        Dim mcName() As String = memPathName.Split(".")
        Dim imc_scan As Integer
        Dim m_scan, currModule As [Module]
        Dim t_scan, currType As Type
        Dim f_scan, currField As FieldInfo
        Dim LoP As List(Of Object)

        currModule = Nothing
        currType = Nothing
        currField = Nothing
        LoP = New list(Of Object)
        Array.Resize(oParents, 0)

        imc_scan = 0
        For Each m_scan In currAssembly.GetModules()
            If (System.IO.Path.GetFileNameWithoutExtension(m_scan.Name) = mcName(imc_scan)) Then
                LoP.Add(m_scan)
                currModule = m_scan
                Exit For
            End If
        Next
        If (currModule Is Nothing) Then
            oParents = LoP.ToArray()
            Return False
        End If
        If (imc_scan >= (mcName.Length - 1)) Then
            oParents = LoP.ToArray()
            Return True
        Else
            imc_scan += 1
            For Each t_scan In currModule.GetTypes()
                If (t_scan.Name = mcName(imc_scan)) Then
                    LoP.Add(t_scan)
                    currType = t_scan
                    Exit For
                End If
            Next
            If (currType Is Nothing) Then
                oParents = LoP.ToArray()
                Return False
            Else
                If (imc_scan >= (mcName.Length - 1)) Then
                    oParents = LoP.ToArray()
                    Return True
                End If

                Dim bf As BindingFlags = BindingFlags.Instance Or BindingFlags.Static Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.IgnoreCase

                While (currType IsNot Nothing) AndAlso currType.IsValueType = False And (imc_scan < (mcName.Length - 1))
                    imc_scan += 1
                    currField = Nothing
                    For Each f_scan In currType.GetFields(bf)
                        If (String.Compare(f_scan.Name, mcName(imc_scan), True) = 0) Then
                            LoP.Add(f_scan)
                            currField = f_scan
                            Exit For
                        End If
                    Next
                    If currField Is Nothing Then
                        oParents = LoP.ToArray()
                        Return False
                    Else
                        dim Container as object = nothing
                        try
                            Container = LoP.Last
                            if (imc_scan >= (mcName.Length - 1)) then
                                Container = LoP(LoP.Count - 2)
                            end if
                            currType = Container
                        catch ex As Exception
                            currType = Nothing
                        end try
                        if ( currType is nothing ) then
                            try
                                Container = Container.GetValue( nothing )
                                LoP.Add( Container.GetType().GetField( mcName( imc_scan+1 ) ) )
                            catch ex1 as Exception
                                MessageBox.Show( ex1.Message )
                            end try
                        end if
                    End If
                End While
            End If
        End If

        oParents = LoP.ToArray()
        Return (imc_scan <= (mcName.Length - 1))
    End Function

    Public Sub Change()
        Dim ao() As Object

        Debug.WriteLine("")
        Debug.WriteLine("---------------------------------------------------")
        Debug.WriteLine("")
        If MemberSearch("sov_reflXn", ao) Then Debug.WriteLine(ao(0).Name)
        If MemberSearch("sov_reflXn.mod1", ao) Then Debug.WriteLine(ao(1).Name)
        If MemberSearch("sov_reflXn.mod1.useDialog", ao) Then Debug.WriteLine(ao(2).Name & " = " & ao(2).GetValue(ao(1)))
        If MemberSearch("sov_reflXn.mod1.PathRoot", ao) Then Debug.WriteLine(ao(2).Name & " = " & ao(2).GetValue(ao(1)))
        If MemberSearch("sov_reflXn.fWin.BoolValue", ao) Then Debug.WriteLine(ao(2).Name & " = " & ao(2).GetValue(ao(1)))
        If MemberSearch("sov_reflXn.fWin.FileRoot", ao) Then Debug.WriteLine(ao(2).Name & " = " & ao(2).GetValue(ao(1)))
        If MemberSearch("sov_reflXn.mod1.MainForm.FileRoot", ao) Then Debug.WriteLine(ao(3).Name & " = " & ao(3).GetValue(ao(2)))
    End Sub
End Module
公共类fWin
公共布尔值为布尔值=真
Public FileRoot As String=“”
私有子fWin_Load(ByVal sender作为对象,ByVal e作为System.EventArgs)处理Me.Load
mod1.MainForm=Me
FileRoot=“我的文件根”
mod2.Change()
端接头
末级
模块mod1
公用对话框作为布尔值
公共路径根为String=“我的路径根”
公共主窗体为fWin
端模块
输入系统。反射
模块mod2
Dim currAssembly As Assembly=Assembly.getExecutionGassembly()
公共函数MemberSearch(memPathName作为字符串,ByRef oParents()作为对象)作为布尔值
Dim mcName()作为字符串=memPathName.Split(“.”)
Dim imc_扫描为整数
Dim m_扫描,当前模块组件[模块]
Dim t_扫描,当前类型为类型
尺寸f_扫描,当前字段作为字段信息
尺寸LoP作为列表(对象)
模块=无
currType=无
currField=无
LoP=新列表(对象)
数组。调整大小(不透明,0)
imc_扫描=0
对于currAssembly.GetModules()中的每个m_扫描
如果(System.IO.Path.GetFileNameWithoutExtension(m_scan.Name)=mcName(imc_scan)),那么
LoP.添加(m_扫描)
电流模块=m_扫描
退出
如果结束
下一个
如果(currModule为Nothing),则
oParents=LoP.ToArray()
返回错误
如果结束
如果(imc_scan>=(mcName.Length-1)),则
oParents=LoP.ToArray()
返回真值
其他的
imc_扫描+=1
对于currModule.GetTypes()中的每个t_扫描
如果(t_scan.Name=mcName(imc_scan)),则
LoP.添加(t_扫描)
currType=t\u扫描
退出
如果结束
下一个
如果(currType为Nothing),则
oParents=LoP.ToArray()
返回错误
其他的
如果(imc_scan>=(mcName.Length-1)),则
oParents=LoP.ToArray()
返回真值
如果结束
Dim bf As BindingFlags=BindingFlags.Instance或BindingFlags.Static或BindingFlags.Public或BindingFlags.NonPublic或BindingFlags.IgnoreCase
While(currType不是空的)和also currType.IsValueType=False和(imc_scan<(mcName.Length-1))
imc_扫描+=1
currField=无
对于currType.GetFields(bf)中的每个f_扫描
如果(String.Compare(f_scan.Name,mcName(imc_scan),True)=0,则
LoP.添加(f_扫描)
currField=f_扫描
退出
如果结束
下一个
如果currField什么都不是
oParents=LoP.ToArray()
返回错误
其他的
将容器变暗为对象=无
尝试
容器=LoP.Last
如果(imc_scan>=(mcName.Length-1)),则
容器=LoP(LoP.Count-2)
如果结束
currType=容器
特例
currType=无
结束尝试
如果(currType为nothing),则
尝试
Container=Container.GetValue(无)
LoP.Add(Container.GetType().GetField(mcName(imc_scan+1)))
捕获ex1作为异常
MessageBox.Show(ex1.Message)
结束尝试
如果结束
如果结束
结束时
如果结束
如果结束
oParents=LoP.ToArray()

Return(imc_scan问题是
FieldInfo.GetValue
需要一个对象实例来获取字段的值,但是您正在向它传递一个
System.Type
:您正在传递
sov_reflXn.fWin
的类型信息,而不是它的一个实例

既然你有这个类型,你可以通过反射得到一个构造函数,但这可能不是你真正想要做的。你需要找到一个好的方法来将你想要操作的实例转化为你的代码

如果模块中有可用的实例,可以在此处使用答案: 将
SetValue
替换为
SetValue
,并将
Nothing
作为实例传递,例如

Call MemberSearch("sov_reflXn.mod1.MainForm.FileRoot", ao)
Debug.WriteLine(ao(1).GetField("PathRoot").GetValue(Nothing))

你说得对。所以我使用变量public MainForm作为fWin,在mod1中声明,并在表单加载事件中设置。但问题仍然存在。如何将fWin/MainForm名称解析到它们的实例中??有一组条件需要检查,以确定我必须做什么:使用GetValue或获取基础实例?@Billy see edited answer.JudIvous搜索应该可以找到有关使用反射获取变量实例的更多信息。上面您在此处编写的Debug.WriteLine(ao(1).GetField(“PathRoot”)…行已在运行。请尝试我代码中的最后一个Debug.WriteLine:您将得到错误…@Billy The
Debug.WriteLine
l