【问题标题】:List(of T) not cooperating with For Each... Next StatementList(of T) 不与 For Each... 下一个语句合作
【发布时间】:2018-06-23 20:27:15
【问题描述】:

我无法准确理解为什么会发生这种情况。

(直到我从雇主那里获得 SQL 权限)我正在开发一个需要身份验证的程序,所以我使用的是 XML 文档,并使用 XDocument 实用程序读取它。一切都正确加载到用户集合中。该集合在名为“UserDatabaseManager”的类中定义为:

收藏:

Private UserCollection As New List(Of User)

UserCollection 的父级定义为:

Public UserDatabaseController As New UserDatabaseManager()

这是用户类:

Public Class User
    'CONSTANTS ----------------------------
    Public Enum RoleCode
        BasicQAAgent = 0
        QAAdministrator = 1
        ITadmin = 5
    End Enum

    'VARIABLES ----------------------------
    Dim uname As String = ""
    Dim fname As String = ""
    Dim pass As String = ""
    Dim userrole As RoleCode = 0
    Dim idnumber As Integer = 0
    Dim createDate As String = ""
    Shared Function SerializeUserFromXMLNode(ByVal XMLelement As XElement) As User
        With XMLelement
            Return New User(.@name, .<fullname>.Value, .<creationday>.Value, .<password>.Value, .<role>.Value)
        End With
    End Function

    Public Sub New(ByVal Name As String, ByVal FullName As String, ByVal CreationDay As String, ByVal PassHash As String, ByVal Role As RoleCode)
        fname = FullName : uname = Name : createDate = CreationDay : pass = PassHash : userrole = Role
    End Sub
    Public ReadOnly Property UserName As String
        Get
            Return uname
        End Get
    End Property
    Public ReadOnly Property FullName As String
        Get
            Return fname
        End Get
    End Property
    Public ReadOnly Property UserRoleCode As RoleCode
        Get
            Return userrole
        End Get
    End Property
    Public ReadOnly Property UserIDNumber As Integer
        Get
             Return idnumber
        End Get
    End Property
    Public ReadOnly Property PasswordMD5Hash As String
        Get
            Return pass
        End Get
    End Property
    Public ReadOnly Property CreationDate As Date
        Get
            Return createDate
        End Get
    End Property
End Class

我创建了自己的用户。断点确认 我的用户 以及所有其他记录都已从 XDocument 成功加载。我能做到:

UserCollection.Item(0)

我的用户类将被返回(我知道我在 xdocument 中的索引为 0)。

现在。如果我想使用其他字段搜索用户怎么办?

我在用户数据库管理器类(用户集合的父类、用户类和 XDocument 工具)中有一个函数,它通过用户,找到与名称匹配的用户,并返回用户的实例到函数的调用:

Public Function GetUserByName(ByVal name As String) As User
    For Each usr As User In UserCollection
        If usr.UserName = name Then
            Return usr
        End If
    Next
    Return Nothing
End Function

总是没有返回,事实上,“If usr.Username...”上的断点确认 ForEach 语句甚至没有运行循环!

所以基本上最终结果是来自登录屏幕的 NullObjectReference。以下是在登录屏幕表单中调用 GetUserByName 的代码:

Private Sub Btn_login_Click(sender As Object, e As EventArgs) Handles btn_login.Click
    DisableLoginElements() 'custom sub
    'try login
    'Try
    Dim inputUsr As String = tbox_Username.Text : Dim inputPass As String = CalculateMD5FromString(tbox_Password.Text)
    tbox_Password.Clear()
    If mainMDI.UserDatabaseController.GetUserByName(inputUsr) IsNot Nothing Then 'HIGHTODO: FIX NULLOBJECTREF FROM USER SEARCH.
        'crosscheck the password provided calculates same MD5 hash as MD5 hash stored in DB. if not, throw MD5calculationVarianceEx Exception
        If mainMDI.UserDatabaseController.GetUserByName(inputUsr).PasswordMD5Hash = inputPass Then
            mainMDI.initializeMainMDIwithUser(mainMDI.UserDatabaseController.GetUserByName(inputUsr)) 'authentication success!
        Else
            Throw MD5calculationVarianceEx 'Password does not match
        End If
    Else
        Throw UserNotFoundEx 'user was not found 
    End If
    'Catch ex As Exception 'an error occured, determine error
    'MsgBox(ex.Message, MsgBoxStyle.Critical, "Login Error: QA Commander")
    'EnableLoginElements()
    'End Try
End Sub

您看到 HIGHTODO 注释的地方是没有返回任何内容的地方。出于调试目的,我注释掉了 Try 语句。

请帮助我在“T”代表的对象内的属性列表中搜索!

编辑:这里是 XML 和 UserDatabaseManager 的完整副本:

用户数据库管理器:

Imports System.Collections.ObjectModel
Imports Microsoft

Public Class UserDatabaseManager

Public ReadOnly UserDatabaseManagerVersion As String = "1.0"

Private ReadOnly DBManager As Integer 'User ID Number of the database administrator
Private Company As String
Private Department As String

Private UserCollectionIndex As New Specialized.StringCollection
Public UserCollection As New List(Of User)

Dim xmlMgr As XDocument


Public Sub New(ByVal Optional databaseXMLPath As String = "")
    If Not databaseXMLPath = "" Then
        'Load datasheet from location
        xmlMgr = XDocument.Load(databaseXMLPath)
        If Not xmlMgr.<UserDB>.<version>.@value = UserDatabaseManagerVersion Then 'User Database is outdated.
            Throw UserDBfileVersionMismatchEX
        End If
        DBManager = xmlMgr.<UserDB>.<dbAdministrator>.@value
        Company = xmlMgr.<UserDB>.<company>.@value
        Department = xmlMgr.<UserDB>.<department>.@value
        Dim usersInDB As IEnumerable(Of XElement) = xmlMgr.Descendants("user")
        For Each elm As XElement In usersInDB
            Dim foundName As String = elm.@name
            Dim userEntry As UserDatabaseManager.User = New User(elm.@name, elm.<fullname>.Value, elm.<creationdate>.Value,
                                                                 elm.<password>.Value, elm.<role>.Value)
            UserCollection.Add(User.SerializeUserFromXMLNode(elm))
        Next
    Else
        'create empty instance
    End If
    'get metadeta from XDocument

End Sub

Public Function GetUserByName(ByVal name As String) As User
    For Each usr As User In UserCollection
        If usr.UserName = name Then
            Return usr
        End If
    Next
    Return Nothing
End Function
Private Function GetUserByID(ByVal ID As Integer) As User
    For Each usr As User In UserCollection
        If usr.UserIDNumber = ID Then
            Return usr : Exit Function
        End If
    Next
    Return Nothing
End Function
Public Class User
    'CONSTANTS ----------------------------
    Public Enum RoleCode
        BasicQAAgent = 0
        QAAdministrator = 1
        ITadmin = 5
    End Enum

    'VARIABLES ----------------------------
    Dim uname As String = ""
    Dim fname As String = ""
    Dim pass As String = ""
    Dim userrole As RoleCode = 0
    Dim idnumber As Integer = 0
    Dim createDate As String = ""
    Shared Function SerializeUserFromXMLNode(ByVal XMLelement As XElement) As User
        With XMLelement
            Return New User(.@name, .<fullname>.Value, .<creationday>.Value, .<password>.Value, .<role>.Value)
        End With
    End Function

    Public Sub New(ByVal Name As String, ByVal FullName As String, ByVal CreationDay As String, ByVal PassHash As String, ByVal Role As RoleCode)
        fname = FullName : uname = Name : createDate = CreationDay : pass = PassHash : userrole = Role
    End Sub

    Public ReadOnly Property UserName As String
        Get
            Return uname
        End Get
    End Property
    Public ReadOnly Property FullName As String
        Get
            Return fname
        End Get
    End Property
    Public ReadOnly Property UserRoleCode As RoleCode
        Get
            Return userrole
        End Get
    End Property
    Public ReadOnly Property UserIDNumber As Integer
        Get
            Return idnumber
        End Get
    End Property
    Public ReadOnly Property PasswordMD5Hash As String
        Get
            Return pass
        End Get
    End Property
    Public ReadOnly Property CreationDate As Date
        Get
            Return createDate
        End Get
    End Property
End Class

数据库 XML:

<UserDB>
  <version value="1.0" />
  <lastEditedDate value="6/21/2018 3:23PM" />
  <dbAdministrator value="0000001" />
  <company value="Anomaly Squared" />
  <department value ="Quality Assurance" />

  <DBPreferences>
    <DefaultPassword>Password18</DefaultPassword>
    <DefaultPasswordHash>E527FABE14F0F6C0C7AD35886614BEAE</DefaultPasswordHash>
    <ForcePassChangeIfDefault>True</ForcePassChangeIfDefault>
  </DBPreferences>



  <QAAgents>
    <user name="mwendel">
      <userid>0000001</userid>
      <password>8814CD66C7804638B4CCE9233CBF4987</password>
      <fullname>Matthew Wendel</fullname>
      <role>5</role>
      <creationdate>6/23/2018</creationdate>
      <activityHistory>
        <action kind="selfCreatedAccount" date="6/23/2018" result="0x0" />
      </activityHistory>
    </user>

    <user name="jappleseed">
      <userid>0185432</userid>
      <password>E527FABE14F0F6C0C7AD35886614BEAE</password>
      <fullname>Johnny Appleseed</fullname>
      <role>1</role>
      <creationdate>6/23/2018</creationdate>
      <activityHistory>
        <result kind="ITCreatedAccount" date="6/23/2018" result="0x0" />
      </activityHistory>
    </user>
  </QAAgents>


</UserDB>
用户角色定义 0 = 基本 QA 代理。 有能力: • 创建新的评估 • 查看已完成的评估 • 添加员工 1 = QA 管理员 与基本相同,但另外: • 添加/创建 QA 代理帐户。 • 可以编辑以前的评估。 • 对基本 QA 代理进行评估 • 添加/编辑/删除活动 5 = IT/系统管理员 完全自主地编辑和维护系统的所有元素。

【问题讨论】:

  • 你能发布你的xml文件吗?
  • 另外,你能不能把UserDatabaseManager的属性也贴出来
  • 感谢您的快速回复!我用我的代码对问题进行了编辑,并为 XML 提供了指向 PasteBin 的链接。
  • 别担心,我会检查一下,看看我能做什么
  • 我无法用UserDatabaseManager 类重现您的问题。但是,我强烈建议您启用 Option Strict 并修复 IDE 发现的问题。

标签: vb.net loops for-loop foreach


【解决方案1】:

哇。我其实可以回答我自己的问题!!!!

因此,当调用 GetUserByName 函数时,它指的是 UserDatabaseManager 的默认实例中的 List(Of User),而不是我声明为 UserDatabaseController 的那个!

使用关键字 Me 非常 很重要,因为它确保函数指向您声明的对象的实例,而不是默认的空集合。这是更新后的功能,一切照旧:

Public Function GetUserByName(ByVal u_name As String) As User
    For Each usr As User In Me.UserCollection
        If usr.UserName = u_name Then
            Return usr
        End If
    Next
    Return Nothing
End Function

“...... Me.UserCollection 中的用户..”中的 Me 标识符基本上解决了这个问题。感谢大家的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 2020-03-18
    • 2018-01-01
    相关资源
    最近更新 更多