Inheritance and design question.

Inheritance and design question.

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


wjcomeaux posted on Friday, October 09, 2009

We have a very generic hierarchy structure that we've defined. The database consists of Hierarchy, HierarchyNode. I've got CSLA objects generated against those tables.

Now, what we want is the ability to do Hierarchy<Merchant> myMerchantHierarchy but this isn't something the CodeSmith templates will allow.

My next proposition was
public class GenericHierarchy<T> :  Hierarchy
However, this won't work either because Hierarchy, being CSLA is created with factory methods and don't expose a constructor.

What I currently have is
GenericHierarchy<T>
{
   public Hierarchy _internalHierarchy;
}
Along with some functions that facilitate the ability to get the data from a node by instantiating an instance of T and calling the LoadData function passing it the dataKey of whatever the current HierarchyNode is.
The problem with this approach is that it forces T to be of a certain type. It can't be an interface because you can't declare instances of an interface.

The solution works except that all of my T objects must now inherit from my AbstractHierarchyNodeData object which means they can no longer inherit from anything else (something a lot of our ojects, like Merchant, already do).
In order to then get a Hierarchy of Merchants we'd have to build a Merchant wrapper that inherits from AbstractHierarchyNodeData.

Also, all of that work and I still can't treat my GenericHierarchy as an actual hierarchy, since it's nothing more than a wrapper around a hierarchy object. Subtle but important difference there.

Any ideas?
Thanks,
Will

wjcomeaux replied on Monday, October 12, 2009

Ok, I did end up writing a workable solution for this. The end result is you can create an instance of T where T implements some interface.

You just can't do new T() without adding new() to the specification of the generic parameter or you can use Activator.CreateInstance(typeof(T)).

However, my supervisor still wants me to do this
public class Hierarchy : BusinessBase
public class GenericHierarchy<T> : Hierarchy

Inheriting directly from CSLA objects won't work because CSLA goes through the factory methods and don't expose a public constructor (at least not a usable one from the code generator). What would we have to do in order to expose the public constructor for our Hierarchy object and not run into any problems with how the DataPortal does its work?

He's thinking that just dropping this code into the constructor would work.
return DataPortal.Fetch< Hierarchy >(new HierarchyCriteria(requiredParameters));
Obviously, this won't work, but there has to be a way to accomplish the same chore in the constructor that doesn't take everything away from how CSLA works.

Thanks,
Will

rsbaker0 replied on Monday, October 12, 2009

Why not just change Hierarchy to Hierarchy[T] -- use <>, I can't get this to format right in this editor -- so that the generic parameter T is used in the entire class chain?

wjcomeaux replied on Tuesday, October 13, 2009

Because Hierarchy is a CSLA object generated with CodeSmith. Making it generic would require that I edit all of the generated code as well which was not a direction we wanted to go with, although it would make the most readible and logical code...

Will

ajj3085 replied on Tuesday, October 13, 2009

Why not just create a new codesmith template designed to your needs?

wjcomeaux replied on Tuesday, October 13, 2009

That's purely a matter of the development effort involved. I'd have to write a template (set of templates) that generate a CSLA object that is generic. All the development and testing involved in that would put me way past my deadline. It would also mean having to keep up with even more differences between the Codesmith.CSLA templates and our custom templates.

Will

Copyright (c) Marimer LLC