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?
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.
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!
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
Can't Linq help you?
this.Select( x=> x).Cast<IListItemInfo>().ToList().AsReadOnly()?
Copyright (c) Marimer LLC