Object design question...
We have three CSLA-based readonly collections and we want to be able to use them interchangeably.
Our first thought was to implement a common interface on the child objects.
But I don't think that gets us all the way to where we need to be.
Implementing an interface on the child objects would make the child objects interchangeable but not the parent objects -- the parent collection objects would still be dealt separately as their different types.
We toyed with the idea of implementing an interface on the parent collection objects, but everybody seemed stumped when we tried to work out the details.
How do we make our three collections interchangeable?
I have some requirements to be able to treat BOs and Collections polymorphically so I implemented Interfaces for them.
BOs:
Public Interface IMyBusinessObjectCollections:
Public Interface IBusinessCollectionThen in my Base class for MyBusinessListBase:
#Region
" IBusinessCollection Implementation " 'useInterface is a fake parameter and is only used to change the method signature so we can Overload the Item method. It does not use the Boolean value at all.#End
Region
Joe
I can summarize the steps as follows:
Note: Try to avoid inheriting interfaces unless the explicitly extend the base interface or are required in order to satisfy the sub-interface.
Joe gives a great example but I'm not sure about the useInterface parameter. Here's how I accomplish this (using C# - just to mix things up):
public interface IChildObject
{
void DoSomething();
}
public interface IParentCollection
{
IChildObject this[int index] { get; }
}
public class ChildObject1 : IChildObject
{
public void DoSomething() { Console.WriteLine("ChildObject1"); }
}
public class ChildObject2 : IChildObject
{
public void DoSomething() { Console.WriteLine("ChildObject2"); }
}
public class ParentCollection1 : ..., IParentCollection
{
Now, you can make use of the collections as follows:
IParentCollection col = new ParentCollection1();
IChildObject child = col[0];
child.DoSomething();
col = new ParentCollection2();
col[0].DoSomething();
In this case, the output will be "ChildObject1" for the first call and "ChildObject2" for the second.
As long as you implement what you need in the IChildObject interface, you can get everything in this manner.
Note: You could implement a common base class for your collections that implements the IParentCollection interface so you don't have to repeat this code. I would suggest making it generic so that you can allow the this[...] (Item in VB) property to be strongly-typed as shown in the example. By placing a constraint that T must implement the IChildObject interface, you'll be all set. Here's how the base collection would look:
public abstract class ParentCollectionBase<T> : ..., IParentCollection
T : IChildObject
{
public abstract T this[int index] { get { ... } }
// This will be pseudo-private
IChildObject IParentCollection.this[int index]
{
get { return this[index] as IChildObject; }
}
}
Now you can derive from this class, specify the appropriate child object type for T, and implement/override this (Item in VB) and you'll have the behavior you are looking for.
I hope that clears things up.
Copyright (c) Marimer LLC