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