我需要保存允许执行某些操作的对象类型列表。
示例 Animal
有 3 个后代Tiger
、Human
、Hippo
我想只允许Tiger
和Hippo
被关在动物园的笼子里?我需要一份动物类型列表。
我会喜欢比List<Type>
更好的东西
这只是一个简化的示例。我不喜欢笼子里的动物。
编辑
因为不清楚。我想在列表中保存对象类型而不是实际对象。
例:
List<Type> types = new List<Type>();
types.Add(typeof(Hippo));
types.Add(typeof(Tiger));
这有一个程序员可以做的types.Add(typeof(Human))
的极限,这就是我不想拒绝的。
编辑2
只是为了澄清我的问题。我希望能够动态Register
允许的类型,并且没有随之而来的if
,因为某些答案在下面。
如果您只需要某些类型的列表:
泛型中没有任何内容可以支持您的请求,因此只需创建一个自定义类型,该类型允许您存储Type
类型并在运行时使用代码来防止无效条目:
public class CagedTypes
{
private readonly List<Type> _types;
public void Add(Type t)
{
if (t == typeof(Hippo) || t == typeof(Tiger))
_types.Add(t);
}
}
虽然我不明白为什么你可能需要这个。
如果您只需要某些类型的列表,则可以选择:
执行与上述相同的操作,但包括下面的界面并将添加检查更改为以下内容:
public void Add(Type t)
{
if (t.GetInterfaces().Contains(typeof(ICanBeHeldInZooCage)))
_types.Add(t);
}
还可以使用属性,因为可以使用 GetAttributes
方法查询任何属性的类型。
如果只希望在列表中包含某些实例:
创建标记接口:
public interface ICanBeHeldInZooCage
Tiger
和Hippo
实现(不必执行任何操作),那么您可以拥有:
var cagedAnimals = new List<ICanBeHeldInZooCage>();
方法1 - 通过接口:
public interface ICageable
{ }
public abstract class Animal
{}
public class Hippo : Animal, ICageable
{}
public class Human : Animal, ICageable
{}
public IEnumerable<Type> GetCageableAnimals()
{
return GetAssemblyTypes(assembly:typeof(Animal).Assembly)
.Where(type=>IsDerivedFrom(type, typeof(Animal)))
.Where(type=>ImplementsInterface(type,typeof(ICageable)));
}
方法 2 - 通过属性:
public class InCageAttribute : Attribute
{ }
public abstract class Animal
{}
[InCage]
public class Hippo : Animal
{}
public class Human : Animal
{}
public IEnumerable<Type> GetCageableAnimals()
{
return GetAssemblyTypes(assembly:typeof(Animal).Assembly)
.Where(type=>IsDerivedFrom(type, typeof(Animal)))
.Where(type=>MarkedByAttribute(type,typeof(InCageAttribute)));
}
更新
重要
这两种方法都只提供运行时检查。 拥有编译检查实现会更好,但不知道如何实现这一点。
UPDATE2对于动态注册:
public class CageRegistry
{
private List<Type> _allowedTypes = new List<Type>();
public IEnumerable<Type> AllowedTypes{get{return _allowedTypes;}}
public bool TryAdd(Type type)
{
if(ImplementsInterface(type, typeof(ICageable)))// for approach with attributes code is pretty similar
{
_allowedTypes.Add(type);
return true;
}
return false;
}
}
PS2
很抱歉没有实现MarkedByAttribute
、IsDerivedFrom
和ImplementsInterface
等方法 - 我只是在当前的机器上还没有视觉工作室,也不记得确切的 api。
接口怎么样?
public interface ICageable {}
public abstract class Animal {}
public class Hippo : Animal, ICageable {}
public class Tiger : Animal, ICageable {}
public class Human : Animal, ICageable {}
public class Ape : Animal {}
....
List<ICageable> ZooAnimals = new List<ICageable>{hippo, tiger, human};
(从人猿星球的角度写作)
如果你需要在列表中使用类型本身,则 well 类型是 Type
类型的实例,因此无论您创建什么,它都将是类型的集合。你可以像这样封装:
public class CageableTypesCollection :
{
private List<Type> _cageableTypes;
public CageableTypesCollection()
{
_cageableTypes = new List<Type>();
}
public RegisterType(Type t)
{
if (!typeof(ICageable).IsAssignableFrom(t))
throw new ArgumentException("wrong type of type");
_cageableTypes.Add(t);
}
public UnregisterType(Type t)
{
....
}
.....
}
我会使用一个接口来确定动物是否是动物动物
public class Animal
{
public string Name;
}
public class Tiger : Animal, IZooAnimal
{
}
public class Human : Animal
{
}
public interface IZooAnimal
{
//Some zoo animal properties
}
然后检查动物是否是动物园动物if (a is IZooAnimal)
下面是您可以使用的动物园类。
public class Zoo
{
public List<IZooAnimal> AnimalsInZoo = new List<IZooAnimal>();
public void AddAnimal(IZooAnimal a)
{
AnimalsInZoo.Add(a);
}
}
编辑:
好的,现在用类型执行此操作并将类型限制为ZooAnimal
我已经制作了一个通用的动物园类,该类采用 T 是 ZooAnimal T
- 在我们的例子中,您可以有一个动物园动物列表或老虎列表。
public class Zoo<T> where T : IZooAnimal
{
public List<Type> AnimalTypes = new List<Type>();
public void AddType(Type a)
{
if (typeof(T) == a)
AnimalTypes.Add(a);
}
}
这将type
老虎添加到AnimalsInZoo
中。希望这对你有用。
Zoo<IZooAnimal> cage = new Zoo<IZooAnimal>();
cage.AddType(typeof(Tiger));
cage.AddType(typeof(Human));
人类是动物,老虎是应该在动物园里的动物。所以在你的情况下,我会为Tiger
和Hippo
再创建一个基类。
public class AnimalInZoo : Animal {}
public class Tiger : AnimalInZoo {}
public class Hippo : AnimalInZoo {}
public class Human : Animal {}
您可以创建帮助程序函数AddInZoo(AnimalInZoo obj)
以添加List<Type> m_Zoo
:
void AddInZoo(AnimalInZoo obj)
{
m_Zoo.Add(obj.GetType());
}
另一个选项:
public abstract class Animal
{
public abstract bool IsCagable { get; }
}
并让嵌套类实现它们的行为。
稍后,在方法中添加的某种Zoo
类主要出现在本主题的答案中,必须在方法中添加进行检查:
public sealed class ZooList : List<Animal> // I believe you need Animal, not Type
{
// ... some implementations ...
public override sealed void Add(Animal animal)
{
if (!animal.IsCagable)
// Prevent from adding.
}
}