使用类类型列表(或类似概念)来限制有效输入

Chr*_* P. 7 .net c#

我有一些继承自抽象基类的类Airplane,例如:

Airplane

-> F15
-> F16
-> Boeing747
Run Code Online (Sandbox Code Playgroud)

假设我想创建另一个类,AirplaneFactory它需要一个可以构建的可能飞机的列表(在构造函数中):

class AirplaneFactory {
    public AirplaneFactory(List<Type> airplaneTypes) {
        ....
    }
}
Run Code Online (Sandbox Code Playgroud)

如何将这些类型限制为仅包含Airplane和继承的类?最终目标是创建不同的AirplaneFactory实例,这些实例只能"构建"指定的特定飞机子集.

我想将它限制在类本身,而不必通过使用enum或使用字符串表示来复制工作.

Jua*_*anR 1

以下是两种可能的实现方式:

 public class AirplaneFactory
 {
    private List<Type> _types = new List<Type>();

    //Implementation 1: Use an internal method to validate all items passed.
    public AirplaneFactory(IEnumerable<Type> airplaneTypes) 
    {
        AddTypes(airplaneTypes);
    }

    private void AddTypes(IEnumerable<Type> airplaneTypes)
    {
        var targetType = typeof(Airplane);            
        foreach (var item in airplaneTypes)
        {
            if (!item.IsSubclassOf(targetType))
                throw new ArgumentException(string.Format("{0} does not derive from {1}", item.FullName, targetType.FullName));
            _types.Add(targetType);
        }
    }        

    //Implementation 2: Use a method to individually add the supported types
    public AirplaneFactory()
    {

    }

    //This method adds types one by one and validates the type
    public void AddType<T>() where T : Airplane
    {
        _types.Add(typeof(T));
    }               
}
Run Code Online (Sandbox Code Playgroud)

(注意使用IEnumerable<T>代替具体列表)

测试它:

  //Implementation 1: It will throw an error when FooClass is checked internally
  var factory = new AirplaneFactory(new[] 
  { 
       typeof(F15), 
       typeof(F16), 
       typeof(Boeing747), 
       typeof(FooClass) 
   });

  //Implementation 2:
  AirplaneFactory factory = new AirplaneFactory();
  factory.AddType<F15>();
  factory.AddType<F16>();
  factory.AddType<Boeing747>();
  //factory.AddType<FooClass>(); //This line would not compile.
Run Code Online (Sandbox Code Playgroud)

更新:

如果抽象出 Airplane Type 集合的概念,还有第三种可能的实现:

public class AirplaneTypeCollection : IEnumerable<Type>
{
    List<Type> _types = new List<Type>();
    public AirplaneTypeCollection()
    {

    }
    public void AddType<T>() where T: Airplane
    {
        _types.Add(typeof(T));
    }

    public IEnumerator GetEnumerator()
    {
        return _types.GetEnumerator();
    }

    IEnumerator<Type> IEnumerable<Type>.GetEnumerator()
    {
        return _types.GetEnumerator();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你的工厂接收该类作为构造函数的参数:

public AirplaneFactory(AirplaneTypeCollection types)
{

}
Run Code Online (Sandbox Code Playgroud)