Using Inheritance

Using Inheritance

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


razorkai posted on Tuesday, May 23, 2006

Hi guys.

We had our first bash at using inheritance within Business Objects yesterday without success.  Basically we have an object called Content of which there are three types - ContentHeader, ContentBody and ContentFooter.  The only real difference between these three types is that they require different security i.e. some users are able to edit a ContentHeader etc.  So we tried creating a Content object and inheriting the other three from this object.  All the data access code is in the Content object, as they all use the same stored procedures and have the same properties.  This means that the dataportal returns a Content object rather than one of the three inherited classes.  How do you structure this so that it would work correctly?  Hope that is clear. 

FWIW, we are probably going down the route of having one object, Content with a ContentType property and working around the problem like that but I feel sure you must be able to use inheritance in Csla just can't see how it is done.  Can anyone enlighten me?

Thanks.

John.

xal replied on Tuesday, May 23, 2006

The short answer: Make Content abstract (MustInherit), so that you can't make instances of it and you don't get confused about it. It only exists to support the actual content types...
Now, once you get past that point, you should be thinking of doing one of two things (assuming you these content classes are children).
1- Have n resultsets that return the different content types and create different child collections for different content types. (You can also selectively fill different collections with one resultset with an approach similar to #2)
2- Return everything in one result set and so something like this in your root:
while dr.read()
Select Case dr.GetByte("ContetType")
    Case 1 'Header
       me.Contents.Add(ContentHeader.GetContentHeader(dr))
    Case 2
       me.Contents.Add(ContentBody.GetContentBody(dr))  
    ....
End Select
Loop

Of course Contents would be accepting / returning objects of type Content.

Andrés

DavidDilworth replied on Tuesday, May 23, 2006

I agree that the abstract base class (ABC) route would be the way to achieve the result.

However, if all the properties of your 3 objects are the same and only the security policy is different then you probably do only have 1 object - the Content object.

It may well have a Content.Type property that allows you to program different behaviour depending on the value it has.

If the 3 subclasses you describe have nothing that makes them different from the base class, then the question must be "What behaviour is this class providing that is different?".

I think if the answer to your question is "None" then you probably don't have a need for a different subclass.

RockfordLhotka replied on Tuesday, May 23, 2006

I think the problem here is that all three objects have the same behavior in that they restrict who has access. If you have a class that defines a Color, you wouldn't create a subclass for a Blue object and a different subclass for a Red object - you'd just make Color a property.

Here you are describing a class that defines authorization, and I don't think it makes sense to create a subclass for objects that only vary based on the data behind that authorization behavior.

In other words (and we're playing semantics here), your objects have the same behavior - just different data. As the object is created (through DataPortal_Create or DataPortal_Fetch) you should be able to examine the criteria object to determine the nature of the object and then load AuthorizationRules at that point (rather than in AddAuthorizationRules like normal).

If you need to authorize the create/fetch behaviors themselves, you may choose to put the customized checks in the factory methods so they run before the data portal is invoked.

McManus replied on Tuesday, May 23, 2006

John,

Since all classes have the same properties and data access code, these should be implemented in the base class (Content). The data access code can be put in a protected Fetch() method.

The Content class should not implement any public Factory methods, because you don't want to create objects of type Content.

In the ContentHeader, ContentBody and ContentFooter classes you can implement the Factory methods. In the DataPortal_Fetch() methods, just call the Fetch() method of the base class. This way, the data access code is not duplicated, and the DataPortal returns the objects you want, i.e. ContentHeader, ContentBody and ContentFooter.

Cheers,

Herman

razorkai replied on Wednesday, May 24, 2006

Thanks to all the people that posted here.  I certainly have some options to look at now. 

John.

Copyright (c) Marimer LLC