我需要保留允许执行某些操作的对象类型列表。
示例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))
的限制,这是我不想解释的。
EDIT2
只是为了澄清我的问题。我希望能够动态Register
允许的类型,而不是后续的if
,因为下面有一些答案。
答案 0 :(得分:4)
如果您只想要某些类型的列表:
泛型中没有任何内容可以支持您的要求,因此只需创建一个自定义类型,允许您存储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 :(得分:3)
界面怎么样?
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};
(从人猿星球的角度写作)
如果您需要列表中的类型本身,则井类型是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)
{
....
}
.....
}
答案 2 :(得分:3)
Approach1 - 通过接口:
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
- 我当前的机器上还没有visual studio,也不记得api。
答案 3 :(得分:2)
我会使用界面来确定动物是否是ZooAnimal
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
,其中T是一个ZooAnimal - 你可以有一个ZooAnimals列表或者我们案例中的老虎名单。
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
Tiger添加到AnimalsInZoo
。希望这对你有用。
Zoo<IZooAnimal> cage = new Zoo<IZooAnimal>();
cage.AddType(typeof(Tiger));
cage.AddType(typeof(Human));
答案 4 :(得分:1)
人类是动物,虎是动物应该在动物园。因此,在您的情况下,我将为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());
}
答案 5 :(得分:0)
另一种选择:
public abstract class Animal
{
public abstract bool IsCagable { get; }
}
让嵌套类实现他们的行为。
稍后,在Add方法中,主要在本主题的答案中呈现的某种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.
}
}