我有一些继承自抽象基类的类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或使用字符串表示来复制工作.
以下是两种可能的实现方式:
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)