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...
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...
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.
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
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.
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
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
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
Copyright (c) Marimer LLC