Class derived from BusinessListBase to hold abstract classes?

Class derived from BusinessListBase to hold abstract classes?

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


kennethkryger posted on Wednesday, March 25, 2009

I'm a CSLA rookie, so please bear with me...

I've got the following object-tree:
- Cylinder that derives from VisualComponent
- Bending that derives from VisualComponent

- VisualComponent (is abstract) derives from PositionalComponent

- PositionalComponent (is abstract) derives from BusinessBase

How do I create a class, that derives from BusinessListBase that holds concrete implementations of VisualComponent (that is Cylinder or Bending classes)?

Kind regards,
Kenneth

RockfordLhotka replied on Wednesday, March 25, 2009

Because generic types are not polymorphic, you need a non-generic base type that is common across all the child objects you want to put into the list. This means using an interface.

BusinessListBase only accepts child objects of type Csla.Core.IEditableBusinessObject, and so your interface must inherit from IEditableBusinessObject:

public interface IVisualComponent : Csla.Core.IEditableBusinessObject
{
}

Have your child classes implement IVisualComponent. Then have your BLB use this type:

public class VisualComponentList :
    BusinessListBase<VisualComponentList, IVisualComponent>
{
}

 

kennethkryger replied on Thursday, March 26, 2009

Okay - so now my VisualComponent class looks like this...

public abstract class VisualComponent : PositionableComponent, IVisualComponent
{
}

But howcome I need to declare my managed backing field like this:

internal static PropertyInfo ConnectionPointListProperty = RegisterProperty(new PropertyInfo("ConnectionPointList"));

and not

internal static PropertyInfo ConnectionPointListProperty = RegisterProperty(c => c.ConnectionPointList);

If I do the latter I get this compile time error:
"Cannot convert lambda expression to type 'Csla.PropertyInfo[BusinessObjects.ConnectionPointList]' because it is not a delegate type"

(please not that [ and ] should be smaller-than and greather-than symbols, but the web page didn't show them...)

It not a big deal - I just want to make sure, what I'm doing is the right thing!

RockfordLhotka replied on Thursday, March 26, 2009

If your base class isn't BusinessBase then the overload of
RegisterProperty() that doesn't require the type name won't work. This is
because that overload uses T to determine the type of your class - which (in
your example) is PositionableComponent rather than VisualComponent.

You can still use the lambda scheme - you'll just need to add some overloads
of RegisterProperty() into your non-generic base class, like I did in
CslaIdentity and CriteriaBase. Those overloads require that the subclass
provide a value for T, somewhat like this:

RegisterProperty(c => c.ConnectionPointList)

That extra generic type parameter allows the overload to know the correct
type for 'c' so it can find your property.

Rocky

rsbaker0 replied on Thursday, March 26, 2009

I think another possibility is to use your own intermediate generic class:

public class VisualComponentList<T> :
    BusinessListBase<VisualComponentList<T>,T> where T : VisualComponent
{

...
}

 

Copyright (c) Marimer LLC