9

我经常发现自己处于创建通用接口或类的情况,然后想以非通用方式使用此类或接口的不同版本。例如我可能有这样的界面:

interface ICanCreate<T>
{
    T NewObject();
}

这允许一个类成为该类型的工厂。然后我想用一个通用的工厂类注册这些,所以我试着写这样的东西:

public class Factory
{
    private Dictionary<Type, ICanCreate> mappings; // what do I put here????

    public void RegisterCreator<T>(ICanCreate<T> creator)
    {            
    }

    public T Create<T>()
    {            
    }
}

在字典中,我使用哪种类型来表示我的价值?我不知道我是否遗漏了某种设计原则,我知道这与 co(ntra?)variance 有很大关系。任何帮助或想法将不胜感激。

4

2 回答 2

11

您要么只需object在字典声明中使用(它都是私有的,并且可以验证您永远不会在其中放入错误的东西)或声明一个扩展的非泛型ICanCreate接口。ICanCreate<T>

基本上,您想要一种无法用 C# 表达的类型关系——无论何时发生这种情况,您最终都会得到一个稍微令人不快的解决方案,但看起来您可以在这里隔离丑陋(即,将其保留在单个类中)。

于 2009-06-17T08:59:22.887 回答
3

有趣的是,这是在 C# 4.0 中解决的问题:

public interface ICanCreate<out T> // covariant
{
    T NewObject();
}

public class Factory
{
    private Dictionary<Type, ICanCreate<object>> mappings = new Dictionary<Type, ICanCreate<object>>();

    public void RegisterCreator<T>(ICanCreate<T> creator) where T:class
    {            
      mappings[typeof(T)] = creator;
    }

    public T Create<T>()
    {            
      ICanCreate<object> creator = mappings[typeof(T)];
      return (T) creator.NewObject(); // I do not think you can get rid of this cast
    }
}
于 2009-06-17T10:23:53.577 回答