我使用从一个抽象基类派生来存储实体项也从一个抽象基类派生泛型集合类的层次结构:

abstract class ItemBase { }

class MyItem : ItemBase
{
    public MyItem()
    {
    }
}


abstract class CollectionBase<T> : Collection<T> where T : ItemBase, new() { }

class MyCollection : CollectionBase<MyItem> { }

该模型的目的是实施对自CollectionBase 派生的任何类的成员严格的类型纪律,以保证这些部件具有默认公共构造。迄今为止它的工作原理。

现在我想创建返回自CollectionBase 派生的类的一个实例的工厂方法。据我所知,通常的做法是:

public CollectionBase<T> CreateCollection<T>();

...也许...

public T Create CreateCollection<T>();

然而,问题是,调用程序不知道什么是“T”是必需的。这是工厂方法本身必须确定收集特定类型的返回。所以,我需要,说:“返回类型将自CollectionBase 获得”非泛型方法签名。我设想这样的事情(如果它是合法的)...

public CollectionBase<> CreateCollection();

我想这是另一个令人棘手的通用差异的问题,但关于这一主题阅读埃里克利珀广泛的解释后甚至,我还不清楚什么,我试图做的是否有可能在C#4.0中可行,以及是否存在是一个简单的解决方法在C#3.0。

在此先感谢您的想法。

有帮助吗?

解决方案

让我们说工厂方法正在创建一个单一的项目。你会:

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
    }
}

其他提示

也许你需要的是:

public CollectionBase<Object> CreateCollection();

由于每个类直接或间接地从对象类继承。

我还没有真正做到这一点,并且道歉,如果它的完全的幼稚,但...

public CollectionBase<Object> CreateCollection();

如果你真的希望它是什么,你可以只返回ICollection的,然后你的消费者可致电.Cast<ItemBase>()扩展方法,因为他们需要。

据我了解,在.NET 4.0中,你将能够返回CollectionBase<ItemBase>,但我还没有尝试过它的测试版呢。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top