KB Article A887
Visible to All Users

How to define a strongly typed collection property

Description:
I have an object A with a one-to-many association with another object B. How can I have a collection of object B strongly typed?

Answer:
First of all, lets define an object that will be used as a child within the one-to-many collection. Call it "Role":

C#
public class Role : XPObject { [Association("User-Role")] public User User; public string Name; }
Visual Basic
Public Class Role Inherits XPObject <Association("User-Role")> _ Public User As User Public Name As String End Class

Now, we need to introduce a master object (lets call it user) that should contain a strongly typed collection of Role objects. Since version 6 of XPO is based upon .Net Framework 2.0 Generics technology, we can easily implement the required functionality using a generic XPCollection<T> generic collection class, as shown below:

C#
public class User : XPObject { [Association("User-Role", typeof(Role))] public XPCollection<Role> UserRoles { get { return GetCollection<Role>("UserRoles"); } } public string FullName; }
Visual Basic
Public Class User Inherits XPObject <Association("User-Role", GetType(Role))> _ Public ReadOnly Property UserRoles() As XPCollection(Of Role) Get Return GetCollection(Of Role)("UserRoles") End Get End Property Public FullName As String End Class

To implement a similar functionality with an old version of .Net Framework and our product, we'll have to create a custom collection that will provide a typed indexed property. Here is a code demonstrating this approach:

C#
public class User : XPObject { public override void Reload() { base.Reload(); Roles.Reload(); } public User() : base() { Roles = new RolesCollection(this, "Roles"); } [Association("User-Role", typeof(Role))] public RolesCollection Roles; public string FullName; } public class RolesCollection : DevExpress.Xpo.Helpers.XPOneToManyCollection { public RolesCollection(IXPSimpleObject owner, string collectionPropertyName) : base(owner, owner.ClassInfo.GetMember(collectionPropertyName)) {} public int Add(Role role) { return base.Add(role); } public new Role this[int index] { get { return (Role)base[index]; } } }
Visual Basic
Imports DevExpress.Xpo Public Class User Inherits XPObject Public Sub New() MyBase.New() Roles = New RolesCollection(Me, "Roles") End Sub Public Overrides Sub Reload() MyBase.Reload() Roles.Reload() End Sub <Association("User-Role", GetType(Role))> _ Public Roles As RolesCollection Public FullName As String End Class Public Class RolesCollection Inherits Helpers.XPOneToManyCollection Public Sub New(ByVal owner As IXPSimpleObject, ByVal collectionPropertyName As String) MyBase.New(owner, owner.ClassInfo.GetMember(collectionPropertyName)) End Sub Public Shadows Function Add(ByVal role As Role) As Integer Return MyBase.Add(role) End Function Public ReadOnly Property Item(ByVal index As Integer) As Role Get Return CType(MyBase.Object(index), Role) End Get End Property End Class

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.