Subclassing BusinessListBase

Subclassing BusinessListBase

Old forum URL: forums.lhotka.net/forums/t/4693.aspx


TooMuch posted on Monday, April 14, 2008

Hi all,

I'm struggling a bit with generics and working with our subclass of BusinessListBase, I have the following so far which works fine:

[Serializable()]

public abstract class CABusinessListBase<T, C> : BusinessListBase<T, C>

where T : CABusinessListBase<T, C>

where C : IEditableBusinessObject

{

// The _parent property must be marked as NonSerialized and NotUndoable so that it is

// safely ignored by both serialization and n-level undo. This is to avoid circular

// references.

// See:

// http://forums.lhotka.net/forums/thread/13793.aspx

[NonSerialized(), NotUndoable()]

private object _parent;

/// <summary>

/// When creating a new BusinessListBase object, you can specify the parent object using this constructor

/// so that you can reference the values of the parent from this newly created child collection.

/// </summary>

/// <param name="parent"></param>

//public CABusinessListBase(object parent)

// : this()

public CABusinessListBase(object parent)

: this()

{

_parent = parent;

}

/// <summary>

/// Normal constructor

/// </summary>

public CABusinessListBase()

: base()

{ }

/// <summary>

/// Get/Set the parent object for this BusinessListBase collection.

/// </summary>

//public CABusinessBase<C> MyParent

public object MyParent

{

get { return _parent; }

set { _parent = value; }

}

}

 

However, I can't seem to figure out how to set the parent declarations so that they are more strongly typed to my CABusinessBase class:

[Serializable()]

public abstract class CABusinessBase<T> : BusinessBase<T>

where T: CABusinessBase<T>

{

}

How do I change the object declarations for the parent variable in my CABusinessListBase to instead be CABusinessBase?  I keep trying CABusinessBase<C>, but that doesn't seem to do the trick.  It's almost like I need a CABusinessBase<U> as the parent is not defined by the T or C...

sergeyb replied on Tuesday, April 15, 2008

Yes, you need another generic parameter for your class, such as

 

public abstract class CABusinessListBase<T, C, P> : BusinessListBase<T, C>

where T : CABusinessListBase<T, C>

where C : IEditableBusinessObject

where P : CABusinessBase<P>

 

then you can define parent as

 

private : CABusinessBase<P> _parent;

 

Having said all that, I think this approach is having problems while not getting much for you in return.  It has the following issues:

1.       It breaks encapsulation by exposing parent on public property

2.       You will still need to cast in your business object when referring to properties or methods of parent.

I am harr pressed to think of any benefits of having parent in your abstract class.

 

 

 

Sergey Barskiy

Senior Consultant

office: 678.405.0687 | mobile: 404.388.1899

Magenic ®

Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: TooMuch [mailto:cslanet@lhotka.net]
Sent: Monday, April 14, 2008 11:27 PM
To: Sergey Barskiy
Subject: [CSLA .NET] Subclassing BusinessListBase

 

Hi all,

I'm struggling a bit with generics and working with our subclass of BusinessListBase, I have the following so far which works fine:

[Serializable()]

public abstract class CABusinessListBase<T, C> : BusinessListBase<T, C>

where T : CABusinessListBase<T, C>

where C : IEditableBusinessObject

{

// The _parent property must be marked as NonSerialized and NotUndoable so that it is

// safely ignored by both serialization and n-level undo. This is to avoid circular

// references.

// See:

// http://forums.lhotka.net/forums/thread/13793.aspx

[NonSerialized(), NotUndoable()]

private object _parent;

/// <summary>

/// When creating a new BusinessListBase object, you can specify the parent object using this constructor

/// so that you can reference the values of the parent from this newly created child collection.

/// </summary>

/// <param name="parent"></param>

//public CABusinessListBase(object parent)

// : this()

public CABusinessListBase(object parent)

: this()

{

_parent = parent;

}

/// <summary>

/// Normal constructor

/// </summary>

public CABusinessListBase()

: base()

{ }

/// <summary>

/// Get/Set the parent object for this BusinessListBase collection.

/// </summary>

//public CABusinessBase<C> MyParent

public object MyParent

{

get { return _parent; }

set { _parent = value; }

}

}

 

However, I can't seem to figure out how to set the parent declarations so that they are more strongly typed to my CABusinessBase class:

[Serializable()]

public abstract class CABusinessBase<T> : BusinessBase<T>

where T: CABusinessBase<T>

{

}

How do I change the object declarations for the parent variable in my CABusinessListBase to instead be CABusinessBase?  I keep trying CABusinessBase<C>, but that doesn't seem to do the trick.  It's almost like I need a CABusinessBase<U> as the parent is not defined by the T or C...



TooMuch replied on Tuesday, April 15, 2008

Sergey,

Thanks for the well explained response, that exactly explains what I was having trouble understanding.  Unfortunately this won't be the best solution for what we need, but it really helps me understand the generics implementation. 

Since the Parent property is currently only needed by 2 of our BLB's, is there a way to have a generic method within our BLB that accepts a generic BusinessBase<P> without adding it to the class signature?  That would give me the flexibility to set the parent property as well as restrict the type to our overrident BusinessBase instead of how I am currently allowing any object.

Let me explain why I have a Parent property in our abstract BLB, and I'd love to hear if there are more optimal solutions to the problem:

The business objects are structured as a parent-child-grandchild in the following way:

BB

      BLB holding a collection of BB's

            BLB holding a collection of BB's

I added the Parent property so that I could set a Parent for the BLB's, much like this thread suggests:
http://forums.lhotka.net/forums/thread/13793.aspx
Each of the BLB's are bound to DataGridViews on a form and when I add a new object to these collections via the overriden AddNewCore in my BLB, I need information about the Parent to create the new object.  I'm definitely like to hear if there are better ways to go about this!

Thanks again.

sergeyb replied on Tuesday, April 15, 2008

What type of information about the parent do you need to create new item? Typically, if all I needed was parent ID, I’d pass that during save process.  If you need a lot more information, you can expose parent.  I have always done this in an instance class though, never in base class.  Also, I never used public modifier, but internal to keep encapsulation from breaking.  In an instance you can set it to specific type, so you can avoid casting.

 

Ex:

 

Public Class ListOfitems:….

 

[Not….]

Private _parent As ListOfItemsParent

Internal ListOfItemsParent  ParentThing … get;set

 

 

Internal static ListOfitems  GetListOfItems(ListOfItemsParent parent)….

// set _parent here

 

 

 

Do not forget to override OnDeserialized in ListOfItemsParent and set ParentThing on your list to ensure your list is pointing to correct parent.

 

Sergey Barskiy

Senior Consultant

office: 678.405.0687 | mobile: 404.388.1899

cid:_2_0648EA840648E85C001BBCB886257279
Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: TooMuch [mailto:cslanet@lhotka.net]
Sent: Tuesday, April 15, 2008 10:13 AM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: Subclassing BusinessListBase

 

Sergey,

Thanks for the well explained response, that's exactly explains what I was having trouble understanding.  Let me explain why I have a Parent property in our abstract BLB, and I'd love to hear if there are more optimal solutions to the problem:

The business objects are structured as a parent-child-grandchild in the following way:

BB

      BLB holding a collection of BB's

            BLB holding a collection of BB's

I added the Parent property so that I could set a Parent for the BLB's, much like this thread suggests:
http://forums.lhotka.net/forums/thread/13793.aspx
Each of the BLB's are bound to DataGridViews on a form and when I add a new object to these collections via the overriden AddNewCore in my BLB, I need information about the Parent to create the new object.  I'm definitely like to hear if there are better ways to go about this!

Thanks again.



TooMuch replied on Tuesday, April 15, 2008

When adding a new row to the DataGridView I set 3 object values that make up the composite key value (Don't want to go down the road of explaining this, they know my thoughts on having a composite key).  If I set these values when creating the new object I can then prohibit the user from adding duplicates rows into the DataGridView way before they even consider performing a Save operation.

You are right about the public modifier, I didn't think through that completely and I've switched it to internal as it is only used in our business objects. 

Regarding the question about a generic method in our abstract BLB - is there any way to do that without having the generic P restriction in the class signature?

Thanks again for your help,
Ryan

sergeyb replied on Tuesday, April 15, 2008

I do not think so.  You can keep declaring it as object and cast it when you use it.  If all you are doing is keeping the user from creating duplicates, can’t you do this based on values that make each row unique on assumption that they all will have the same parent class’s data?

 

Sergey Barskiy

Senior Consultant

office: 678.405.0687 | mobile: 404.388.1899

cid:_2_0648EA840648E85C001BBCB886257279
Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: TooMuch [mailto:cslanet@lhotka.net]
Sent: Tuesday, April 15, 2008 10:35 AM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: RE: Subclassing BusinessListBase

 

When adding a new row to the DataGridView I set 3 object values that make up the composite key value (Don't want to go down the road of explaining this, they know my thoughts on having a composite key).  If I set these values when creating the new object I can then prohibit the user from adding duplicates rows into the DataGridView way before they even consider performing a Save operation.

You are right about the public modifier, I didn't think through that completely and I've switched it to internal as it is only used in our business objects. 

Regarding the question about a generic method in our abstract BLB - is there any way to do that without having the generic P restriction in the class signature?

Thanks again for your help,
Ryan



TooMuch replied on Tuesday, April 15, 2008

Thinking through what you've said about shying away from putting the Parent property in the abstract BLB, I think the better implementation would be to do as you say and put the Parent property in the instance BLB class.  It is only needed in two cases so their would be minimal redundant code to write.  Thanks for your insights, it is all much clearer to me now!

Copyright (c) Marimer LLC