Asp classic 我的验证器应该访问我的整个模型吗?

Asp classic 我的验证器应该访问我的整个模型吗?,asp-classic,single-responsibility-principle,Asp Classic,Single Responsibility Principle,正如标题所述,我想知道我的验证类是否有权访问模型中的所有属性。理想情况下,我希望这样做,因为有些字段需要10+个其他字段来验证它是否有效。我可以但不希望有10个以上参数的函数。或者这会使模型和验证器过于耦合吗?这里有一个小例子来说明我的意思。但是,这段代码不起作用,因为它给出了一个无限循环 Class User Private m_UserID Private m_Validator Public Sub Class_Initialize() End Sub

正如标题所述,我想知道我的验证类是否有权访问模型中的所有属性。理想情况下,我希望这样做,因为有些字段需要10+个其他字段来验证它是否有效。我可以但不希望有10个以上参数的函数。或者这会使模型和验证器过于耦合吗?这里有一个小例子来说明我的意思。但是,这段代码不起作用,因为它给出了一个无限循环

Class User
    Private m_UserID
    Private m_Validator

    Public Sub Class_Initialize()
    End Sub

    Public Property Let Validator(value)
        Set m_Validator = value

        m_Validator.Initialize(Me)
    End Property

    Public Property Get Validator()
        Validator = m_Validator
    End Property

    Public Property Let UserID(value)
        m_UserID = value
    End property

    Public Property Get UserID()
        UserID = m_Validator.IsUserIDValid()
    End property End Class

Class Validator
    Private m_User

    Public Sub Class_Initialize()
    End Sub

    Public Sub Initialize(value)
        Set m_User = value
    End Sub

    Public Function IsUserIDValid()
        IsUserIDValid = m_User.UserID > 13
    End Function End Class

Dim mike : Set mike = New User 

mike.UserID = 123456  mike.Validator = New Validator

Response.Write mike.UserID
如果我是对的,而且这是一个好主意,那么我如何才能使用get属性UserID修复无限循环呢

多谢各位

解决方案

td{padding:4px;}
误差
{
背景#F00F00;
}
td.警告
{
背景#FC0;
}
400那么
Set validationObject=New ValidationError
如果m_高度=324,则
Set validationObject=New ValidationWarning
其他的
Set validationObject=New ValidationSuccess
如果结束
validationObject.CellValue=m_高度
Set Validate=validationObject
端函数
末级
类验证错误
私人m_CSSClass
私有m_值
公共属性获取CSSClass()
CSSClass=“错误”
端属性
公共财产出租价值(价值)
m_CellValue=值
端属性
公共属性获取CellValue()
CellValue=m_CellValue
端属性
末级
类验证警告
私人m_CSSClass
私有m_值
公共属性获取CSSClass()
CSSClass=“警告”
端属性
公共财产出租价值(价值)
m_CellValue=值
端属性
公共属性获取CellValue()
CellValue=m_CellValue
端属性
末级
类验证成功
私人m_CSSClass
私有m_值
公共属性获取CSSClass()
CSSClass=“”
端属性
公共财产出租价值(价值)
m_CellValue=值
端属性
公共属性获取CellValue()
CellValue=m_CellValue
端属性
末级
类模型验证器
公共函数ValidateModel(模型)
Dim modelValidation:设置modelValidation=New CollectionClass
'验证名称
Dim名称:集合名称=新名称验证
name.Init model.name
模型验证。添加名称
“验证年龄
尺寸年龄:设置年龄=新年龄验证
age.Init model.age
模型验证。添加年龄
'验证高度
尺寸高度:设置高度=新高度验证
height.Init model.height
模型验证。添加高度
Dim validatedProperties:Set validatedProperties=New CollectionClass
Dim模型值
对于modelvalization.Items()中的每个modelVal
validatedProperties.Add modelVal.Validate()
下一个
设置ValidateModel=validatedProperties
端函数
末级
Dim modelCollection:设置modelCollection=New CollectionClass
Dim user1:Set user1=新用户模型
user1.Name=“迈克”
用户1.年龄=12
user1.Height=32
modelCollection.adduser1
Dim user2:Set user2=新用户模型
user2.Name=“菲尔”
用户2.年龄=18
user2.Height=432
modelCollection.adduser2
Dim user3:Set user3=新用户模型
user3.Name=“Michele”
user3.Age=32
user3.Height=324
modelCollection.adduser3
'验证集合中的所有模型
Dim模型值
Dim validatedModels:Set validatedModels=New CollectionClass
对于modelCollection.Items()中的每个modelValue
Dim objModelValidator:设置objModelValidator=New ModelValidator
validatedModels.AddObjModelValidator.ValidateModel(modelValue)
下一个
%>
名称
年龄
高度
产生

虽然不完美,但它比我开始的要好得多。基本上,我决定使用装饰图案。我的下一步很可能是从每个validate中删除Init()函数,并用SetModel()函数或其他东西替换它。这样,每个验证都可以访问模型中的每个属性


谢谢大家。

我通常定义一个验证器来验证整个模型;在本例中,我将有一个UserValidator类,该类有一个接受用户并返回ValidationResult的方法,其中包括一个验证错误列表


这允许您在不影响验证的情况下更改用户类的实现(例如,您不必每次添加新属性时都向验证器类添加新方法,或者如果您希望更改用户标识的验证方式,则不必更改方法签名,等等).

我认为您让验证器验证整个模型是正确的。要打破无限循环,可以将值传递给验证器

Public Property Get UserID()
     UserID = m_Validator.IsUserIDValid(m_userID)
End property 

// in Validator
Public Function IsUserIDValid(userID)
    IsUserIDValid = userID > 13
End Function
或者,如果您更喜欢封装,可以添加友元函数来访问属性,而无需验证

Public Property Get UserID()
     UserID = m_Validator.IsUserIDValid()
End property 

Friend Function GetUserID()
   GetUserID = m_userID
End Function

// in Validator
Public Function IsUserIDValid()
    // "private" access - to get the unvalidated property
    IsUserIDValid = m_user.GetUserID > 13
End Function
第三种方法是将对象与验证分离。基类未经验证定义所有属性。然后定义添加验证的子类:

class User
    Private m_userID
    Public Property Get UserID()
         UserID = m_userID
    End property 
End Class

class ValidatedUser inherits User
   Public Overrides Property Get UserID()
       if (m_userID<15)
           // handle invalid case, e.g. throw exception with property that is invalid
       UserID = m_userID
   End Property

   Public Function Validate()
    ' class-level validation
   End Function
End Class
在上一个示例中,ValidateUser看起来与原始代码类似,但关键区别在于ValidateUser本身没有任何属性值-它将所有属性访问器委托给m_用户对象。验证器使用m_user对象,该对象提供简单的属性而无需验证,因此无限递归就消失了

目前,在检索属性时进行验证。我认为这样做是因为您希望在使用数据之前对其进行验证,并避免在分配属性时出现短暂的验证错误。除了特性级验证外,您可能还需要定义一个“整个对象”验证方法,用于检查对象上的所有特性,特别是涉及多特性约束的特性。例如,如果约束A+B+C<50,则将A B和C作为单独的属性进行检查将导致
class User
    Private m_userID
    Public Property Get UserID()
         UserID = m_userID
    End property 
End Class

class ValidatedUser inherits User
   Public Overrides Property Get UserID()
       if (m_userID<15)
           // handle invalid case, e.g. throw exception with property that is invalid
       UserID = m_userID
   End Property

   Public Function Validate()
    ' class-level validation
   End Function
End Class
Class MustInherit User
   Public MustInherit Property Get UserID()
End Class

' A simple implementation of User that provides the properties
Class DefaultUser Inherits User
   Private m_UserID
   Public Overrides Property Get UserID()
      UserID = m_UserID
   End Property   
End Class

Class ValidatedUser Inherits User
   private Validator m_validator
   private User m_User

   Public Property Let Validator(value)
        Set m_Validator = value
        m_Validator.Initialize(m_User)
        ' note that validator uses m_User - this breaks the infinite recursion
    End Property

   Public Overrides Property Let UserID(value)
      m_User.UserID = value;
   End Property

   Public Overrides Property Get UserID()
      UserID = m_validator.IsUserValid();
   End Property
End Class   
' User is now a simple class (like DefaultUser above '
' with just properties, no validation '
Class UserValidator

   Public Function Validate(user)
     ' validate the given user object, return a list of
     ' validation errors, each validation error object
     ' that describes the property or properties
     ' that caused the validation error and why it's an error     
     ' E.g. '
     Dim ve As ValidationError 
     ve = new ValidationError
     ve.obj = user;   ' the object that failed validation
     ve.property = "userID"
     ve.msg = "userId must be < 15"
     ' potentially put several of these in a list and return to caller     
   End
End Class