Expose ReadOnlyListBase through Interface?

Expose ReadOnlyListBase through Interface?

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


hurcane posted on Monday, March 14, 2011

I have two object graphs that need to be used interchangeably by a method. The graph is a simple read-only root object, read-only child list, and read-only child object.

I have defined Interfaces for the root and child objects, but I am getting stuck with how to expose the basic functionality of the list. The method needs to be able to access the Count property and enumerate the collection.

Putting some concrete values on this:

StockItem (ReadOnlyBase) implements IItemInfo

StockItemPrices (ReadOnlyListBase) implements ???

StockItemPrice (ReadOnlyBase) implements IItemPriceInfo

My other object graph is similar in structure, but consists of CatalogItem, CatalogItemPrices, and CatalogItemPrice objects.

IItemInfo needs a property to expose the prices collection. I think I want to expose it as an interface, but how do I also expose the Item and Count properties, as well as the enumerator, which are all features built into the classes?

RockfordLhotka replied on Monday, March 14, 2011

You can probably use one of the standard enumeration/list/collection interfaces already implemented by ReadOnlyListBase. It is a subclass of ObservableCollection (CSLA 4) or BindingList (3.8 and older).

Those Microsoft base classes implement IEnumerable<T>, IList<T>, and (I think) ICollection<T>. They implement some non-generic version as well.

IEnumerable is where foreach and LINQ start working.

I think IList is where the Count property comes in.

hurcane replied on Tuesday, March 15, 2011

Thanks, Rocky.

I had gone this route, trying the following:

Interface IItemInfo

...

ReadOnly Property Prices As IItemPricesInfo

...

End Interface

Interface IItemPricesInfo : Inherits IList(Of IItemPriceInfo)

Function GetPriceFor(OrderDate As Date) As IItemPriceInfo

End Interface

When I did this, the read-only list classes needed implementations of the IList methods for type IItemPriceInfo. This was getting messier than I wanted.

Then I realized I could move my GetPriceFor method into the parent class. The property prices could simply be exposed as IList(Of IItemPriceInfo). A simple cast is all that I needed in the parent class.

Thanks again!

hurcane replied on Wednesday, March 16, 2011

Another followup to this issue. The "simple" cast that I referenced in my previous post turns out not to be so simple, at least in .NET 2.0. I know .NET 4.0 has some enhancements with regard to covariance and contravariance, but I don't think that applies to using Interfaces.

You cannot directly cast ReadOnlyListBase(Of ListInfo, ListItemInfo) to IList(Of ListItemInfo).

Instead, something like the following is needed:

Dim newList As List(Of ListItemInfo)

For Each listItem In ROBList

newList.Add(listItem)

Next

return newList.AsReadOnly

ajj3085 replied on Wednesday, March 16, 2011

Can't Linq help you? 

this.Select( x=> x).Cast<IListItemInfo>().ToList().AsReadOnly()?

Copyright (c) Marimer LLC