I am using CSLA.
I have Contact Class. Doctor and Employee derived from Contact.
I have Contacts which is a collection of Contact.
Now Doctors and Employees are derived from contacts. I have something different to do with those collections. Doctors is collection of Doctor. Employees is collection of Employee.
Problem with validation rule, where the parent of Doctor is not the collection of Doctor (Doctors) . Following is the source code. And forgive my ignorance with object oriented technology.
////// Contact.vb //////////////
Imports Csla
Namespace CSLAParentChild
Public MustInherit Class Contact(Of C As Contact(Of C))
Inherits MistyBase(Of C)
#Region " Business Methods "
Public Enum Properties
ContactId
ContactTypeId
ContactName
Title
Country
End Enum
Protected _ContactID As Guid
Protected _ContactTypeID As Guid
Protected _ContactName As String = String.Empty
Protected _Title As String = String.Empty
Protected _Country As String = String.Empty
Protected Friend Sub New()
'Required for inheritance
MarkAsChild()
End Sub
Public Property ContactId() As Guid
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Get
CanReadProperty(True)
Return _ContactID
End Get
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Set(ByVal value As Guid)
CanWriteProperty(True)
If Not _ContactID.Equals(value) Then
_ContactID = value
PropertyHasChanged()
End If
End Set
End Property
Public ReadOnly Property ContactTypeId() As Guid
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Get
CanReadProperty(True)
Return _ContactTypeID
End Get
End Property
Public Property ContactName() As String
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Get
CanReadProperty(True)
If _ContactName.Trim = "" OrElse String.IsNullOrEmpty(_ContactName) Then
Return "Provide Name"
Else
Return _ContactName
End If
End Get
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Set(ByVal value As String)
CanWriteProperty(True)
If Not _ContactName.Equals(value) Then
_ContactName = value
PropertyHasChanged()
End If
End Set
End Property
Public Property Title() As String
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Get
CanReadProperty(True)
Return _Title
End Get
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Set(ByVal value As String)
CanWriteProperty(True)
If Not _Title.Equals(value) Then
_Title = value
PropertyHasChanged()
End If
End Set
End Property
Public Property Country() As String
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Get
CanReadProperty(True)
Return _Country
End Get
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Set(ByVal value As String)
CanWriteProperty(True)
If Not _Country.Equals(value) Then
_Country = value
PropertyHasChanged()
End If
End Set
End Property
#End Region
#Region " Validation Rules "
Protected Overrides Sub AddBusinessRules()
ValidationRules.AddRule(AddressOf Validation.CommonRules.StringMaxLength, New Validation.CommonRules.MaxLengthRuleArgs(Properties.ContactName.ToString, 50))
ValidationRules.AddRule(AddressOf Validation.CommonRules.StringMaxLength, New Validation.CommonRules.MaxLengthRuleArgs(Properties.Title.ToString, 50))
End Sub
#End Region
End Class
End Namespace
/////// Contacts.vb
Imports Csla
Namespace CSLAParentChild
<Serializable()> _
Public MustInherit Class Contacts(Of T As Contacts(Of T, C), C As Contact(Of C))
Inherits MistyListBase(Of T, C)
#Region " Business Methods "
Protected Overrides Function AddNewCore() As Object
Throw New ApplicationException("Not Supported")
End Function
Public Overloads Sub Remove(ByVal contactId As Guid)
For Each Item As C In Me
If Item.ContactId = contactId Then
Item.IsActive = False
End If
Next
End Sub
Public Overloads Function Contains(ByVal contactId As Guid) As Boolean
For Each Item As C In Me
If Item.ContactId = contactId AndAlso _
Item.IsActive Then
Return True
End If
Next
Return False
End Function
Public Function FindById(ByVal contactId As Guid) As C
For Each Item As C In Me
If Item.ContactId = contactId Then
Return Item
End If
Next
Return Nothing
End Function
#End Region
End Class
End Namespace
//////////Doctor.VB
Imports Csla
Namespace CSLAParentChild
<Serializable()> _
Public Class Doctor
Inherits Contact(Of Doctor)
#Region " Validation Rules "
Protected Overrides Sub AddBusinessRules()
MyBase.AddBusinessRules()
ValidationRules.AddRule(AddressOf Validation.CommonRules.StringRequired, Properties.ContactName.ToString)
ValidationRules.AddRule(Of Doctor)(AddressOf DuplicatesNotAllowed, "ContactName", 1)
ValidationRules.ProcessThroughPriority = 0
End Sub
Private Shared Function DuplicatesNotAllowed(Of T As Doctor)(ByVal target As T, ByVal e As Validation.RuleArgs) As Boolean
Dim parent As Doctors = DirectCast(target.Parent, Doctors)
For Each existingItem As Doctor In parent
If existingItem.ContactName.ToLower = target.ContactName.ToLower AndAlso _
Not ReferenceEquals(existingItem, target) Then
e.Description = "Duplicate Doctor"
e.Severity = Validation.RuleSeverity.Error
Return False
End If
Next
Return True
End Function
#End Region
#Region " Factory Methods "
Friend Shared Function NewContact(ByVal contactName As String) As Doctor
Return New Doctor(contactName)
End Function
Friend Shared Function GetContact(ByVal contactId As Guid) As Doctor
Return Nothing
End Function
Public Sub New()
'MarkAsChild()
End Sub
Private Sub New(ByVal contactName As String)
'MarkAsChild()
Me.ContactName = contactName
MarkAsChild()
End Sub
#End Region
End Class
End Namespace
////////Doctors.VB
Imports Csla
Namespace CSLAParentChild
<Serializable()> _
Public Class Doctors
Inherits Contacts(Of Doctors, Doctor)
#Region " Factory Methods "
Friend Shared Function NewContacts() As Doctors
Return New Doctors
End Function
Friend Sub New()
' require use of factory methods
MarkAsChild()
End Sub
Public Function AddContact(ByVal contactName As String) As Doctor
Dim newContact As Doctor = Nothing
newContact = Doctor.NewContact(contactName)
Me.Add(newContact)
Return newContact
End Function
#End Region
End Class
End Namespace
//////IEditableMistyObject.vb
Public Interface IEditableMistyObject
Inherits Csla.Core.IEditableBusinessObject
ReadOnly Property ID() As Guid
Property IsActive() As Boolean
End Interface
////////MistyBase.vb
Imports Csla
Namespace CSLAParentChild
Public MustInherit Class MistyBase(Of T As MistyBase(Of T))
Inherits BusinessBase(Of T)
Implements IEditableMistyObject
Protected Friend _ObjectID As Guid = Guid.NewGuid
Protected Friend _LastModifiedDate As Date = Date.MinValue
Protected Friend _IsActive As Boolean = True
<System.ComponentModel.DataObjectField(True, True)> _
Public ReadOnly Property ID() As Guid Implements IEditableMistyObject.ID
Get
Return _ObjectID
End Get
End Property
Public Property IsActive() As Boolean Implements IEditableMistyObject.IsActive
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Get
CanReadProperty(True)
Return _IsActive
End Get
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Set(ByVal value As Boolean)
CanWriteProperty(True)
If Not _IsActive.Equals(value) Then
_IsActive = value
PropertyHasChanged()
End If
End Set
End Property
Public ReadOnly Property LastModifiedDate() As String
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Get
CanReadProperty(True)
If _LastModifiedDate = Date.MinValue Then
Return "NOT SUBMITTED"
Else
Return _LastModifiedDate.ToLocalTime.ToString
End If
End Get
End Property
Protected Overrides Function GetIdValue() As Object
Return _ObjectID
End Function
End Class
End Namespace
//////MistyListBase.vb
Imports Csla
Namespace CSLAParentChild
Public MustInherit Class MistyListBase(Of T As MistyListBase(Of T, C), C As IEditableMistyObject)
Inherits BusinessListBase(Of T, C)
Public Shadows Sub RemoveItem(ByVal itemId As Guid)
InActivateItem(itemId)
End Sub
Public Shadows Sub Remove(ByVal itemId As Guid)
InActivateItem(itemId)
End Sub
Public Shadows Sub Remove(ByVal item As C)
InActivateItem(item.ID)
End Sub
Public Shadows Sub RemoveAt(ByVal index As Integer)
Me(index).IsActive = False
End Sub
Public Overridable Sub InActivateItem(ByVal itemId As Guid)
For Each Item As C In Me
If Item.ID = itemId Then
Item.IsActive = False
Exit For
End If
Next
End Sub
Public Overloads Property Item(ByVal id As Guid) As C
Get
For Each child As C In Me
If child.ID = id Then
Return child
End If
Next
Return Nothing
End Get
Set(ByVal value As C)
For Each child As C In Me
If child.ID = id Then
child = value
Exit For
End If
Next
End Set
End Property
Public ReadOnly Property IsSavable() As Boolean
Get
If IsValid AndAlso IsDirty Then
Return True
End If
Return False
End Get
End Property
End Class
End Namespace
//////Module1.VB - for test
Imports CSLAParentChild.CSLAParentChild
Module Module1
Sub Main()
Dim docs As Doctors = Doctors.NewContacts()
docs.AddContact("George")
docs.AddContact("David")
' Here adding duplicate, it goes to validation (DuplicatesNotAllowed) but target.parent is nothing,
docs.AddContact("George")
If docs.IsValid Then
End If
End Sub
End Module
FYI - your property code is no longer supported and you should change it.
No need for the attribute anymore - plus you *must* pass the string property name (or a propertyinfo object) to CanReadProperty. You *cannot* rely on the original stack trace code to locate the property name for you.
=============================================
<System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
Get
CanReadProperty(True)
==============================================
Joe
Joe,
I do really appreciate your response. I did the necessary changes. I hate to ask you to do my job, but I was not still able to get the target.parent working. By that I mean that the "parent" is not having the collection (Doctors). The "target" is the "Doctor".
Really appreciate for identifying the correct way of doing things.
- Abir
Copyright (c) Marimer LLC