18、业务对象实现全解析

业务对象实现全解析

在开发业务应用时,业务对象的实现至关重要。它不仅涉及到代码的结构和逻辑,还与业务规则、数据验证以及权限控制等方面紧密相关。本文将详细介绍业务对象的实现过程,包括类的声明、属性的定义、业务和验证规则的设置以及授权规则的配置等内容。

1. 项目设置

在开始实现业务对象之前,需要进行项目的设置。业务类可以放置在类库、Windows 应用程序或网站类型的项目中。但为了充分利用移动对象和 CSLA .NET 框架的优势,建议将业务类放在类库项目中。这样可以使业务对象被不同的前端使用,满足实际应用中多界面的需求。

在 Visual Studio 中,创建一个类库项目,并引用 Csla.dll 程序集。如果使用企业服务功能,可能还需要引用 System.EnterpriseServices.dll。引用 Csla.dll 可以通过“添加引用”对话框完成,如下所示:

' 引用 Csla.dll
' 通过“添加引用”对话框设置参考
2. 业务类实现

接下来,我们将详细介绍几个重要的业务类的实现。

2.1 Project 类

Project 类是一个可编辑的根类,代表应用程序中的一个项目。它继承自 BusinessBase 类,并包含以下几个主要区域:
- 业务方法 :包含实例字段的声明、属性和实现业务逻辑的方法。
- 业务和验证规则 :实现 AddBusinessRules() 方法,关联验证规则到属性。
- 授权规则 :实现 AddAuthorizationRules() 和 AddObjectAuthorizationRules() 方法,定义属性和对象的授权规则。
- 工厂方法 :用于创建和加载对象。
- 数据访问 :实现对象的持久化和数据访问。

以下是 Project 类的部分代码示例:

Imports System
Imports System.Linq
Imports Csla
Imports Csla.Data
Imports Csla.Security

Namespace ProjectTracker.Library
    <Serializable()> _
    Public Class Project
        Inherits BusinessBase(Of Project)

        ' 注册 Id 属性
        Private Shared IdProperty As PropertyInfo(Of Guid) = _
            RegisterProperty(New PropertyInfo(Of Guid)("Id"))

        ' 只读属性 Id
        <System.ComponentModel.DataObjectField(True, True)> _
        Public ReadOnly Property Id() As Guid
            Get
                Return GetProperty(IdProperty)
            End Get
        End Property

        ' 注册 Name 属性
        Private Shared NameProperty As PropertyInfo(Of String) = _
            RegisterProperty(New PropertyInfo(Of String)("Name", "Project name"))

        ' 读写属性 Name
        Public Property Name() As String
            Get
                Return GetProperty(NameProperty)
            End Get
            Set(ByVal value As String)
                SetProperty(NameProperty, value)
            End Set
        End Property

        ' 其他属性和方法
    End Class
End Namespace

在上述代码中,我们定义了只读属性 Id 和读写属性 Name。使用 GetProperty() 和 SetProperty() 方法可以自动检查授权规则并执行相应的操作。

2.2 ProjectResources 类

ProjectResources 类是一个集合类,用于管理项目的资源分配。它继承自 Csla.BusinessListBase 类,包含以下几个区域:
- 业务方法 :包含 Assign() 方法,用于将资源分配给项目。
- 工厂方法 :用于创建和加载集合。
- 数据访问 :实现集合的数据加载和保存。

以下是 ProjectResources 类的部分代码示例:

<Serializable()> _
Public Class ProjectResources
    Inherits BusinessListBase(Of ProjectResources, ProjectResource)

    ' 注册 Resources 属性
    Private Shared ResourcesProperty As PropertyInfo(Of ProjectResources) = _
        RegisterProperty(New PropertyInfo(Of ProjectResources)("Resources"))

    ' 只读属性 Resources
    Public ReadOnly Property Resources() As ProjectResources
        Get
            If Not (FieldManager.FieldExists(ResourcesProperty)) Then
                LoadProperty(ResourcesProperty, ProjectResources.NewProjectResources())
            End If
            Return GetProperty(ResourcesProperty)
        End Get
    End Property

    ' 业务方法 Assign
    Public Sub Assign(ByVal resourceId As Integer)
        If Not Contains(resourceId) Then
            Dim resource = ProjectResource.NewProjectResource(resourceId)
            Me.Add(resource)
        Else
            Throw New InvalidOperationException("Resource already assigned to project")
        End If
    End Sub

    ' 其他方法
End Class

在上述代码中,我们定义了只读属性 Resources 和业务方法 Assign。Assign 方法用于将资源分配给项目,并检查资源是否已经分配。

2.3 ProjectResource 类

ProjectResource 类是一个可编辑的子对象类,代表分配给项目的资源。它继承自 BusinessBase 类,并实现了 IHoldRoles 接口。包含以下几个区域:
- 业务方法 :包含 GetResource() 方法,用于获取资源对象。
- 业务和验证规则 :实现 AddBusinessRules() 方法,关联验证规则到属性。
- 授权规则 :实现 AddAuthorizationRules() 方法,定义属性的授权规则。
- 工厂方法 :用于创建和加载对象。
- 数据访问 :实现对象的持久化和数据访问。

以下是 ProjectResource 类的部分代码示例:

<Serializable()> _
Public Class ProjectResource
    Inherits BusinessBase(Of ProjectResource)
    Implements IHoldRoles

    ' 业务方法 GetResource
    Public Function GetResource() As Resource
        CanExecuteMethod("GetResource", True)
        Return Resource.GetResource(GetProperty(ResourceIdProperty))
    End Function

    ' 业务和验证规则
    Protected Overrides Sub AddBusinessRules()
        ValidationRules.AddRule(Of ProjectResource)( _
            Assignment.ValidRole, RoleProperty)
    End Sub

    ' 授权规则
    Protected Overrides Sub AddAuthorizationRules()
        AuthorizationRules.AllowWrite(RoleProperty, "ProjectManager")
        AuthorizationRules.DenyExecute("GetResource", "Guest")
    End Sub

    ' 其他方法
End Class

在上述代码中,我们定义了业务方法 GetResource、业务和验证规则以及授权规则。GetResource 方法用于获取资源对象,并检查用户的授权。

3. 业务和验证规则

业务和验证规则是业务对象实现的重要组成部分。通过实现 AddBusinessRules() 方法,可以将验证规则关联到属性。以下是 Project 类的 AddBusinessRules() 方法示例:

Protected Overrides Sub AddBusinessRules()
    ValidationRules.AddRule(Csla.Validation.CommonRules.StringRequired, _
        New Csla.Validation.RuleArgs(NameProperty))
    ValidationRules.AddRule(Csla.Validation.CommonRules.StringMaxLength, _
        New Csla.Validation.CommonRules.MaxLengthRuleArgs(NameProperty, 50))
    ValidationRules.AddRule(Of Project)( _
        StartDateGTEndDate(Of Project), StartedProperty)
    ValidationRules.AddRule(Of Project)( _
        StartDateGTEndDate(Of Project), EndedProperty)
    ValidationRules.AddDependentProperty( _
        StartedProperty, EndedProperty, True)
End Sub

在上述代码中,我们关联了多个验证规则到属性,包括字符串必填、字符串最大长度、日期比较等规则。同时,使用 AddDependentProperty() 方法处理相互依赖的属性。

4. 授权规则

授权规则用于控制用户对属性和对象的访问权限。通过实现 AddAuthorizationRules() 和 AddObjectAuthorizationRules() 方法,可以定义属性和对象的授权规则。以下是 Project 类的授权规则示例:

Protected Overrides Sub AddAuthorizationRules()
    AuthorizationRules.AllowWrite(NameProperty, "ProjectManager")
    AuthorizationRules.AllowWrite(StartedProperty, "ProjectManager")
    AuthorizationRules.AllowWrite(EndedProperty, "ProjectManager")
    AuthorizationRules.AllowWrite(DescriptionProperty, "ProjectManager")
End Sub

Protected Shared Sub AddObjectAuthorizationRules()
    AuthorizationRules.AllowCreate(GetType(Project), "ProjectManager")
    AuthorizationRules.AllowEdit(GetType(Project), "ProjectManager")
    AuthorizationRules.AllowDelete(GetType(Project), "ProjectManager")
    AuthorizationRules.AllowDelete(GetType(Project), "Administrator")
End Sub

在上述代码中,我们定义了属性的写入权限和对象的创建、编辑、删除权限。只有“ProjectManager”角色的用户可以修改属性,“ProjectManager”和“Administrator”角色的用户可以执行对象的相关操作。

5. 其他业务类

除了上述介绍的类,还有一些其他重要的业务类,如 Resource、ProjectResources、ProjectResource、Assignment、RoleList、Roles、Role 等。这些类在实现上与前面介绍的类类似,但各自具有不同的特点和功能。

以下是 Resource 类的部分代码示例:

Private Shared IdProperty As PropertyInfo(Of Integer) = _
    RegisterProperty(New PropertyInfo(Of Integer)("Id"))
Private _id As Integer = IdProperty.DefaultValue
<System.ComponentModel.DataObjectField(True, True)> _
Public ReadOnly Property Id() As Integer
    Get
        Return GetProperty(IdProperty, _id)
    End Get
End Property

Private Shared FirstNameProperty As PropertyInfo(Of String) = _
    RegisterProperty(New PropertyInfo(Of String)("FirstName", "First name"))
Private _firstName As String = FirstNameProperty.DefaultValue
Public Property FirstName() As String
    Get
        Return GetProperty(FirstNameProperty, _firstName)
    End Get
    Set(ByVal value As String)
        SetProperty(FirstNameProperty, _firstName, value)
    End Set
End Property

在上述代码中,Resource 类使用了私有备份字段来存储属性值,并通过 GetProperty() 和 SetProperty() 方法进行访问和设置。

6. 自定义身份验证

应用程序可以使用 Windows 集成身份验证或自定义身份验证。自定义身份验证需要创建自定义的主体和身份类。以下是 PTPrincipal 和 PTIdentity 类的实现示例:

' PTPrincipal 类
<Serializable()> _
Public Class PTPrincipal
    Inherits Csla.Security.BusinessPrincipalBase

    Private Sub New(ByVal identity As IIdentity)
        MyBase.New(identity)
    End Sub

    Public Shared Function Login(ByVal username As String, _
      ByVal password As String) As Boolean
        Return SetPrincipal(PTIdentity.GetIdentity(username, password))
    End Function

    Public Shared Sub LoadPrincipal(ByVal username As String)
        SetPrincipal(PTIdentity.GetIdentity(username))
    End Sub

    Private Shared Function SetPrincipal(ByVal identity As PTIdentity) As Boolean
        If identity.IsAuthenticated Then
            Dim principal As New PTPrincipal(identity)
            Csla.ApplicationContext.User = principal
        End If
        Return identity.IsAuthenticated
    End Function

    Public Shared Sub Logout()
        Csla.ApplicationContext.User = New UnauthenticatedPrincipal()
    End Sub
End Class

' PTIdentity 类
<Serializable()> _
Public Class PTIdentity
    Inherits CslaIdentity

    ' 数据访问代码将在后续章节讨论
End Class

在上述代码中,PTPrincipal 类用于管理用户的身份验证和授权,PTIdentity 类用于验证用户的凭据和检索用户的角色。

7. 总结

通过以上的介绍,我们详细了解了业务对象的实现过程,包括项目设置、业务类的实现、业务和验证规则的设置以及授权规则的配置等内容。这些业务对象的实现将为后续创建 WPF、Web Forms 和 XML 服务接口提供基础。

以下是业务对象实现的主要步骤总结:
1. 进行项目设置,将业务类放在类库项目中,并引用必要的程序集。
2. 实现业务类,包括类的声明、属性的定义、业务和验证规则的设置以及授权规则的配置。
3. 处理业务和验证规则,确保数据的有效性和一致性。
4. 配置授权规则,控制用户对属性和对象的访问权限。
5. 实现自定义身份验证,满足应用程序的安全需求。

通过合理的设计和实现,业务对象可以更好地支持业务逻辑,提高代码的可维护性和可扩展性。

业务对象实现全解析(续)

8. 业务方法详解

在前面的介绍中,我们已经了解了业务类的基本结构和主要区域。下面将详细介绍业务方法的实现细节。

8.1 只读属性

只读属性通常用于表示对象的唯一标识符或不可修改的信息。以 Project 类的 Id 属性为例:

Private Shared IdProperty As PropertyInfo(Of Guid) = _
    RegisterProperty(New PropertyInfo(Of Guid)("Id"))
<System.ComponentModel.DataObjectField(True, True)> _
Public ReadOnly Property Id() As Guid
    Get
        Return GetProperty(IdProperty)
    End Get
End Property

在上述代码中,Id 属性是只读的,它代表对象在数据库中的唯一主键值。使用 GetProperty() 方法可以自动检查用户的授权规则,并返回属性值。

8.2 读写属性

读写属性允许用户修改对象的属性值。以 Project 类的 Name 属性为例:

Private Shared NameProperty As PropertyInfo(Of String) = _
    RegisterProperty(New PropertyInfo(Of String)("Name", "Project name"))
Public Property Name() As String
    Get
        Return GetProperty(NameProperty)
    End Get
    Set(ByVal value As String)
        SetProperty(NameProperty, value)
    End Set
End Property

在上述代码中,Name 属性是读写的。SetProperty() 方法会执行一系列操作,包括检查用户的授权、确保新值与现有值不同、触发属性更改事件、执行验证规则等。

8.3 SmartDate 属性

处理日期属性时,使用 SmartDate 类可以简化操作。以 Project 类的 Started 属性为例:

Private Shared StartedProperty As PropertyInfo(Of SmartDate) = _
    RegisterProperty(New PropertyInfo(Of SmartDate)("Started"))
Public Property Started() As String
    Get
        Return GetPropertyConvert(Of SmartDate, String)(StartedProperty)
    End Get
    Set(ByVal value As String)
        SetPropertyConvert(Of SmartDate, String)(StartedProperty, value)
    End Set
End Property

在上述代码中,Started 属性是一个字符串属性,但实际上存储的是 SmartDate 类型的值。通过 GetPropertyConvert() 和 SetPropertyConvert() 方法,可以实现类型的转换,使 UI 可以方便地处理日期值。

8.4 子集合属性

子集合属性用于访问对象的子对象集合。以 Project 类的 Resources 属性为例:

Private Shared ResourcesProperty As PropertyInfo(Of ProjectResources) = _
    RegisterProperty(New PropertyInfo(Of ProjectResources)("Resources"))
Public ReadOnly Property Resources() As ProjectResources
    Get
        If Not (FieldManager.FieldExists(ResourcesProperty)) Then
            LoadProperty(ResourcesProperty, ProjectResources.NewProjectResources())
        End If
        Return GetProperty(ResourcesProperty)
    End Get
End Property

在上述代码中,Resources 属性是一个只读属性,它返回一个 ProjectResources 集合。使用懒加载的方式,只有在需要时才会创建子集合。

9. 业务和验证规则深入分析

业务和验证规则是确保数据有效性和一致性的重要手段。下面将深入分析业务和验证规则的实现。

9.1 AddBusinessRules() 方法

AddBusinessRules() 方法用于关联验证规则到属性。以 Project 类为例:

Protected Overrides Sub AddBusinessRules()
    ValidationRules.AddRule(Csla.Validation.CommonRules.StringRequired, _
        New Csla.Validation.RuleArgs(NameProperty))
    ValidationRules.AddRule(Csla.Validation.CommonRules.StringMaxLength, _
        New Csla.Validation.CommonRules.MaxLengthRuleArgs(NameProperty, 50))
    ValidationRules.AddRule(Of Project)( _
        StartDateGTEndDate(Of Project), StartedProperty)
    ValidationRules.AddRule(Of Project)( _
        StartDateGTEndDate(Of Project), EndedProperty)
    ValidationRules.AddDependentProperty( _
        StartedProperty, EndedProperty, True)
End Sub

在上述代码中,我们关联了多个验证规则到属性,包括字符串必填、字符串最大长度、日期比较等规则。同时,使用 AddDependentProperty() 方法处理相互依赖的属性。

9.2 自定义规则方法

除了使用 CommonRules 类中的规则方法,还可以实现自定义规则方法。以 Project 类的 StartDateGTEndDate 规则为例:

Private Shared Function StartDateGTEndDate(Of T As Project)( _
    ByVal target As T, ByVal e As Csla.Validation.RuleArgs) As Boolean
    If target.ReadProperty(StartedProperty) > _
       target.ReadProperty(EndedProperty) Then
        e.Description = "Start date can't be after end date"
        Return False
    Else
        Return True
    End If
End Function

在上述代码中,StartDateGTEndDate 规则用于确保项目的开始日期不晚于结束日期。如果规则被违反,将设置错误描述并返回 False。

10. 授权规则详细配置

授权规则用于控制用户对属性和对象的访问权限。下面将详细介绍授权规则的配置。

10.1 AddAuthorizationRules() 方法

AddAuthorizationRules() 方法用于定义属性的授权规则。以 Project 类为例:

Protected Overrides Sub AddAuthorizationRules()
    AuthorizationRules.AllowWrite(NameProperty, "ProjectManager")
    AuthorizationRules.AllowWrite(StartedProperty, "ProjectManager")
    AuthorizationRules.AllowWrite(EndedProperty, "ProjectManager")
    AuthorizationRules.AllowWrite(DescriptionProperty, "ProjectManager")
End Sub

在上述代码中,只有“ProjectManager”角色的用户可以修改这些属性。如果用户没有相应的权限,SetProperty() 方法将抛出异常。

10.2 AddObjectAuthorizationRules() 方法

AddObjectAuthorizationRules() 方法用于定义对象的授权规则。以 Project 类为例:

Protected Shared Sub AddObjectAuthorizationRules()
    AuthorizationRules.AllowCreate(GetType(Project), "ProjectManager")
    AuthorizationRules.AllowEdit(GetType(Project), "ProjectManager")
    AuthorizationRules.AllowDelete(GetType(Project), "ProjectManager")
    AuthorizationRules.AllowDelete(GetType(Project), "Administrator")
End Sub

在上述代码中,“ProjectManager”角色的用户可以创建、编辑和删除 Project 对象,“Administrator”角色的用户也可以删除对象。

11. 其他业务类补充说明

除了前面详细介绍的类,还有一些其他业务类也具有重要的功能。

11.1 ProjectResources 类

ProjectResources 类是一个集合类,用于管理项目的资源分配。它包含一些有用的业务方法,如 Assign()、GetItem()、Remove() 等。

' Assign 方法
Public Sub Assign(ByVal resourceId As Integer)
    If Not Contains(resourceId) Then
        Dim resource = ProjectResource.NewProjectResource(resourceId)
        Me.Add(resource)
    Else
        Throw New InvalidOperationException("Resource already assigned to project")
    End If
End Sub

' GetItem 方法
Public Function GetItem(ByVal resourceId As Integer) As ProjectResource
    Return Me.SingleOrDefault(Function(r) r.ResourceId = resourceId)
End Function

' Remove 方法
Public Sub Remove(ByVal resourceId As Integer)
    For Each res As ProjectResource In Me
        If res.ResourceId = resourceId Then
            Remove(res)
            Exit For
        End If
    Next
End Sub

在上述代码中,Assign() 方法用于将资源分配给项目,GetItem() 方法用于根据资源 Id 获取子对象,Remove() 方法用于根据资源 Id 删除子对象。

11.2 Role 类

Role 类是一个可编辑的子对象类,代表角色信息。它的 Id 属性是用户输入的值,需要处理默认值和重复值的问题。

' 设置默认值
Private Shared IdProperty As PropertyInfo(Of Integer) = _
    RegisterProperty(New PropertyInfo(Of Integer)("Id"))
Private _idSet As Boolean
Public Property Id() As Integer
    Get
        If Not _idSet Then
            _idSet = True
            SetProperty(IdProperty, GetMax() + 1)
        End If
        Return GetProperty(IdProperty)
    End Get
    Set(ByVal value As Integer)
        _idSet = True
        SetProperty(IdProperty, value)
    End Set
End Property

' 获取最大值
Private Function GetMax() As Integer
    Dim parent As Roles = DirectCast(Me.Parent, Roles)
    Return parent.Max(Function(r) r.Id)
End Function

' 防止重复值
Private Shared Function NoDuplicates(Of T As Role)(ByVal target As T, _
    ByVal e As Csla.Validation.RuleArgs) As Boolean
    Dim parent As Roles = DirectCast(target.Parent, Roles)
    If parent IsNot Nothing Then
        For Each item As Role In parent
            If item.Id = target.ReadProperty(IdProperty) AndAlso _
                Not (ReferenceEquals(item, target)) Then
                e.Description = "Role Id must be unique"
                Return False
            End If
        Next
    End If
    Return True
End Function

在上述代码中,Id 属性在第一次读取时会设置默认值,同时通过 NoDuplicates 规则防止重复值。

12. 总结与展望

通过以上的详细介绍,我们全面了解了业务对象的实现过程,包括业务方法、业务和验证规则、授权规则等方面。这些知识将帮助我们更好地设计和实现业务逻辑,提高代码的质量和可维护性。

在实际应用中,还可以进一步优化业务对象的实现,例如使用更复杂的业务规则、优化授权机制、提高数据访问效率等。同时,结合不同的前端技术,如 WPF、Web Forms 和 XML 服务接口,可以为用户提供更好的体验。

总之,业务对象的实现是一个复杂而重要的过程,需要我们不断学习和实践,以满足不同业务场景的需求。通过合理的设计和实现,我们可以构建出高效、稳定、安全的业务应用系统。

以下是业务对象实现的关键要点总结:
1. 业务方法:包括只读属性、读写属性、SmartDate 属性和子集合属性的实现。
2. 业务和验证规则:通过 AddBusinessRules() 方法关联验证规则,使用自定义规则方法处理特殊需求。
3. 授权规则:通过 AddAuthorizationRules() 和 AddObjectAuthorizationRules() 方法定义属性和对象的授权规则。
4. 其他业务类:如 ProjectResources 类和 Role 类,各自具有独特的功能和实现方式。

通过掌握这些要点,我们可以更加熟练地实现业务对象,为业务应用的开发打下坚实的基础。

业务对象实现全解析(续)

12. 只读集合的实现

在业务应用中,只读集合用于高效地向用户展示数据列表。例如 ProjectList 和 ResourceList 类,它们都是只读数据的集合,通过继承 ReadOnlyListBase 类来实现。下面以 ResourceList 类为例进行说明。

<Serializable()> _
Public Class ResourceList
    Inherits ReadOnlyListBase(Of ResourceList, ResourceInfo)
End Class

ReadOnlyListBase 类需要两个泛型类型参数,第一个是集合对象本身的类型,用于创建强类型的 Clone() 方法;第二个是集合中包含的子对象类型。ResourceList 集合包含的是 ResourceInfo 类型的只读子对象。

ResourceInfo 类实现了简单的只读属性来暴露资源数据:

<Serializable()> _
Public Class ResourceInfo
    Inherits ReadOnlyBase(Of ResourceInfo)

    Private _id As Integer
    Public ReadOnly Property Id() As Integer
        Get
            Return _id
        End Get
    End Property

    Private _name As String
    Public ReadOnly Property Name() As String
        Get
            Return _name
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return _name
    End Function
End Class

这里没有使用字段管理器,因为对于简单的只读对象,如果没有授权规则,字段管理器并不会提供实际价值。同时,重写 ToString() 方法,使得在将集合数据绑定到列表控件(如 ListBox)时,能正确显示资源名称。

13. 可编辑根集合的实现

Roles 类是一个可编辑的根集合,它包含了一系列可编辑的子 Role 对象。该类继承自 BusinessListBase,以下是其类声明:

<Serializable()> _
Public Class Roles
    Inherits BusinessListBase(Of Roles, Role)
End Class

Roles 类有几个重要的业务方法:

13.1 Remove 方法

该方法接受角色的 Id 值,用于简化子对象的移除操作,特别是在后续创建的 Web Forms UI 中会很有用。

Public Sub Remove(ByVal id As Integer)
    For Each item As Role In Me
        If item.Id = id Then
            Remove(item)
            Exit For
        End If
    Next
End Sub
13.2 GetRoleById 方法

用于根据角色 Id 值检索子 Role 对象。

Public Function GetRoleById(ByVal id As Integer) As Role
    For Each item As Role In Me
        If item.Id = id Then
            Return item
        End If
    Next
    Return Nothing
End Function
13.3 AddNewCore 方法

当使用 WPF 或 Windows Forms 数据绑定时,如果允许网格控件在用户移动到最后一行时自动向集合中添加新项,集合对象需要重写 AddNewCore() 方法。

Protected Overrides Function AddNewCore() As Object
    Dim item As Role = Role.NewRole()
    Add(item)
    Return item
End Function

同时,在构造函数中设置 AllowNew 属性为 True 来启用此功能:

Private Sub New()
    AddHandler Me.Saved, AddressOf Roles_Saved
    Me.AllowNew = True
End Sub
14. Role 类的特殊处理

Role 类作为可编辑的子对象,其 Id 属性是用户输入的值,这就需要特殊处理默认值和重复值的问题。

14.1 设置默认值

在 Id 属性的 Get 方法中,如果该属性尚未设置值,则会调用 GetMax() 方法获取当前列表中 Id 的最大值,并将属性值设置为该最大值加 1。

Private Shared IdProperty As PropertyInfo(Of Integer) = _
    RegisterProperty(New PropertyInfo(Of Integer)("Id"))
Private _idSet As Boolean
Public Property Id() As Integer
    Get
        If Not _idSet Then
            _idSet = True
            SetProperty(IdProperty, GetMax() + 1)
        End If
        Return GetProperty(IdProperty)
    End Get
    Set(ByVal value As Integer)
        _idSet = True
        SetProperty(IdProperty, value)
    End Set
End Property

Private Function GetMax() As Integer
    Dim parent As Roles = DirectCast(Me.Parent, Roles)
    Return parent.Max(Function(r) r.Id)
End Function
14.2 防止重复值

通过实现 NoDuplicates 规则方法,在用户输入 Id 值时检查是否存在重复值。

Private Shared Function NoDuplicates(Of T As Role)(ByVal target As T, _
    ByVal e As Csla.Validation.RuleArgs) As Boolean
    Dim parent As Roles = DirectCast(target.Parent, Roles)
    If parent IsNot Nothing Then
        For Each item As Role In parent
            If item.Id = target.ReadProperty(IdProperty) AndAlso _
                Not (ReferenceEquals(item, target)) Then
                e.Description = "Role Id must be unique"
                Return False
            End If
        Next
    End If
    Return True
End Function

在 AddBusinessRules() 方法中关联该规则到 Id 属性:

Protected Overrides Sub AddBusinessRules()
    ValidationRules.AddRule(Of Role)(NoDuplicates, IdProperty)
    ValidationRules.AddRule( _
        Csla.Validation.CommonRules.StringRequired, NameProperty)
End Sub
15. Exists 命令的实现思路

实现 Exists() 命令可以让 UI 开发者快速判断某个对象的数据是否存在于数据库中,而无需完全实例化该对象。这可以通过使用 Csla.CommandBase 创建命令对象来实现,该命令主要是运行数据库中的存储过程并报告结果。虽然具体代码将在后续详细介绍,但以下是一个理想的 UI 代码示例:

If Project.Exists(productId) Then
    ' 执行相应操作
End If
16. 自定义身份验证的详细流程

自定义身份验证需要创建自定义的主体和身份类,以下是 PTPrincipal 和 PTIdentity 类的详细实现和工作流程。

16.1 PTPrincipal 类

PTPrincipal 类继承自 Csla.Security.BusinessPrincipalBase,用于管理用户的身份验证和授权。

<Serializable()> _
Public Class PTPrincipal
    Inherits Csla.Security.BusinessPrincipalBase

    Private Sub New(ByVal identity As IIdentity)
        MyBase.New(identity)
    End Sub

    Public Shared Function Login(ByVal username As String, _
      ByVal password As String) As Boolean
        Return SetPrincipal(PTIdentity.GetIdentity(username, password))
    End Function

    Public Shared Sub LoadPrincipal(ByVal username As String)
        SetPrincipal(PTIdentity.GetIdentity(username))
    End Sub

    Private Shared Function SetPrincipal(ByVal identity As PTIdentity) As Boolean
        If identity.IsAuthenticated Then
            Dim principal As New PTPrincipal(identity)
            Csla.ApplicationContext.User = principal
        End If
        Return identity.IsAuthenticated
    End Function

    Public Shared Sub Logout()
        Csla.ApplicationContext.User = New UnauthenticatedPrincipal()
    End Sub
End Class

其工作流程如下:
1. Login 方法 :调用 PTIdentity 的 GetIdentity 方法进行身份验证,根据返回的身份对象创建 PTPrincipal 对象,并设置为当前主体。
2. LoadPrincipal 方法 :在不需要重新验证凭据的情况下,根据用户名重新加载身份对象,并设置当前主体。
3. Logout 方法 :将当前主体设置为未认证的主体对象。

16.2 PTIdentity 类

PTIdentity 类继承自 CslaIdentity,负责验证用户的凭据和检索用户的角色。

<Serializable()> _
Public Class PTIdentity
    Inherits CslaIdentity

    ' 数据访问代码将在后续章节讨论
End Class
17. 总结与拓展

通过以上对各种业务类的详细介绍,我们全面掌握了业务对象的实现过程,包括类的声明、属性定义、业务和验证规则设置、授权规则配置以及自定义身份验证等方面。这些知识为构建高效、稳定、安全的业务应用系统提供了坚实的基础。

在实际开发中,我们可以根据具体业务需求对这些业务对象进行拓展和优化。例如:
- 业务规则拓展 :可以实现更复杂的业务规则,处理更多的业务场景。
- 授权机制优化 :结合不同的安全策略,进一步细化授权规则,提高系统的安全性。
- 数据访问优化 :采用更高效的数据访问方式,如缓存技术、异步数据访问等,提升系统性能。

同时,结合不同的前端技术,如 WPF、Web Forms 和 XML 服务接口,可以为用户提供多样化的交互体验。总之,业务对象的实现是一个不断学习和实践的过程,我们需要根据实际情况灵活运用所学知识,以满足不同业务场景的需求。

以下是业务对象实现的整体要点总结表格:
| 要点分类 | 具体内容 |
| — | — |
| 业务方法 | 包含只读属性、读写属性、SmartDate 属性、子集合属性的实现,以及 ProjectResources 类的 Assign、GetItem、Remove 等方法 |
| 业务和验证规则 | 通过 AddBusinessRules() 方法关联验证规则,使用自定义规则方法(如 StartDateGTEndDate、NoDuplicates)处理特殊需求 |
| 授权规则 | 通过 AddAuthorizationRules() 和 AddObjectAuthorizationRules() 方法定义属性和对象的授权规则 |
| 其他业务类 | 如 ResourceList 类实现只读集合,Roles 类实现可编辑根集合,Role 类处理特殊的 Id 属性问题 |
| 自定义身份验证 | 通过 PTPrincipal 和 PTIdentity 类实现自定义身份验证流程 |

通过掌握这些要点,我们能够更加熟练地实现业务对象,为业务应用的开发提供有力支持。

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    A(业务对象实现) --> B(业务方法)
    A --> C(业务和验证规则)
    A --> D(授权规则)
    A --> E(其他业务类)
    A --> F(自定义身份验证)
    B --> B1(只读属性)
    B --> B2(读写属性)
    B --> B3(SmartDate 属性)
    B --> B4(子集合属性)
    C --> C1(AddBusinessRules 方法)
    C --> C2(自定义规则方法)
    D --> D1(AddAuthorizationRules 方法)
    D --> D2(AddObjectAuthorizationRules 方法)
    E --> E1(ReadOnlyListBase 类)
    E --> E2(BusinessListBase 类)
    E --> E3(Role 类特殊处理)
    F --> F1(PTPrincipal 类)
    F --> F2(PTIdentity 类)

这个流程图展示了业务对象实现的主要组成部分及其子部分,帮助我们更清晰地理解业务对象实现的整体结构。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值