我使用的是泛型集合类的层次结构,它派生自一个抽象基类来存储也来自抽象基类的实体项:
abstract class ItemBase { }
class MyItem : ItemBase
{
public MyItem()
{
}
}
abstract class CollectionBase<T> : Collection<T> where T : ItemBase, new() { }
class MyCollection : CollectionBase<MyItem> { }
该模型的目标是对源自CollectionBase&lt; T&gt;的任何类的成员强制执行严格的类型规则。并保证这些成员具有默认的公共构造函数。到目前为止它的确有效。
现在我想创建一个工厂方法,该方法返回从CollectionBase&lt; T&gt;派生的类的实例。我理解通常的方法是:
public CollectionBase<T> CreateCollection<T>();
...或者......或者......
public T Create CreateCollection<T>();
然而,问题是调用例程不知道需要什么“T”。工厂方法本身必须确定要返回的特定类型的集合。所以我需要一个非通用的方法签名,说“返回类型将派生自CollectionBase&lt; T&gt;”。我设想这样的事情(如果它是合法的)......
public CollectionBase<> CreateCollection();
我认为这是另一个棘手的通用差异问题,但即使在阅读了Eric Lippert关于这个主题的广泛解释之后,我仍然不清楚我想要做的是否可能在C#4.0中是可行的,以及是否存在是C#3.0中的一个简单的解决方法。
提前感谢您的想法。
答案 0 :(得分:1)
假设工厂方法正在创建单个项目。你会:
public ItemBase CreateItem();
您必须使用ItemBase
,因为您无法了解更具体的内容。将该原则应用于收集方法,您将得到:
public CollectionBase<ItemBase> CreateCollection();
由于缺乏差异,您需要一个从CollectionBase<ItemBase>
派生的适配器类,并包装创建的实际集合。
在C#4.0中,您只需返回实际的集合。
编辑:工厂可能看起来像这样,嵌入了适配器:
public class CollectionFactory
{
public CollectionBase<ItemBase> CreateCollection()
{
if(someCondition)
{
return CreateAdapter(new MyCollection());
}
else
{
return CreateAdapter(new MyOtherCollection());
}
}
private static CollectionAdapter<T> CreateAdapter<T>(CollectionBase<T> collection) where T : ItemBase, new()
{
return new CollectionAdapter<T>(collection);
}
private class CollectionAdapter<T> : CollectionBase<ItemBase> where T : ItemBase, new()
{
private CollectionBase<T> _collection;
internal CollectionAdapter(CollectionBase<T> collection)
{
_collection = collection;
}
// Implement CollectionBase API by passing through to _collection
}
}
答案 1 :(得分:0)
您可能需要的是:
public CollectionBase<Object> CreateCollection();
由于每个类都直接或间接地从Object类继承。
答案 2 :(得分:0)
我实际上并没有这样做,如果完全天真,我会道歉,但......
public CollectionBase<Object> CreateCollection();
答案 3 :(得分:0)
如果你真的希望它成为任何东西,你可以只返回ICollection,然后你的消费者可以根据需要调用.Cast<ItemBase>()
扩展方法。
根据我的理解,在.NET 4.0中你可以返回CollectionBase<ItemBase>
,但我还没有尝试过它。