我可以保存同一后代的对象类型列表<>吗?



我需要保存允许执行某些操作的对象类型列表。

示例 Animal 有 3 个后代TigerHumanHippo

我想只允许TigerHippo被关在动物园的笼子里?我需要一份动物类型列表。

我会喜欢比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

TigerHippo实现(不必执行任何操作),那么您可以拥有:

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
很抱歉没有实现MarkedByAttributeIsDerivedFromImplementsInterface等方法 - 我只是在当前的机器上还没有视觉工作室,也不记得确切的 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));

人类是动物,老虎是应该在动物园里的动物。所以在你的情况下,我会为TigerHippo再创建一个基类。

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.
    }
}

最新更新