I am trying to write a factory method that will create a derived instance of an abstract generic collection class. Here are the base classes ...
abstract class ItemBase { }
abstract class CollectionBase<T> : Collection<T> where T : ItemBase, new() { }
...and their derived classes ...
class Item : ItemBase { }
class ItemCollection : CollectionBase<Item> {}
Now, I want a factory method that will create an ItemCollection. But note that the derived classes Item and ItemCollection are unknown to the class that contains this factory method. This is how I imagine it should be ...
static T CreateItemCollection<T>() where T : CollectionBase<ItemBase>, new()
{
return new T();
}
... and I imagine invoking it thus ...
var collection = CreateItemCollection<ItemCollection>();
But the factory method won't compile because ItemBase must have a parameterless constructor. And the invokation call refuses to believe that ItemCollection
is derived from CollectionBase<ItemBase>
.
Can someone please point me in the right direction? Thanks.
ItemCollection
isn't derived from CollectionBase<ItemBase>
, due to generic invariance. After all, you can add an ItemBase
to a CollectionBase<ItemBase>
- but you don't want that for your ItemCollection
!
You need to make the method generic in two type parameters:
static T CreateItemCollection<TCollection, TItem>()
where TCollection : CollectionBase<TItem>, new()
where TItem : ItemBase
{
return new TCollection();
}
Only the collection type needs a parameterless constructor. You'd call this with:
var collection = CreateItemCollection<ItemCollection, Item>();