6

特定のアクションを実行できるオブジェクト タイプのリストを保持する必要があります。

Animalには 3 つの子孫がありますTiger, Human,Hippo

と だけTigerHippo動物園の檻に入れたいのですが?動物の種類のリストが必要です。

私はより良いものを愛するだろうList<Type>

これは単なる単純化された例です。檻の中の動物は好きじゃない..

編集

はっきりしないので。実際のオブジェクトではなく、オブジェクトの種類をリストに保持したい。

例:

List<Type> types = new List<Type>();
types.Add(typeof(Hippo));
types.Add(typeof(Tiger));

これにはプログラマーができる限界がありtypes.Add(typeof(Human))、これは私が否定したくないことです。

編集2

私の質問を明確にするために。以下のいくつかの回答として、動的にRegister型を許可し、結果として s を持たないようにしたいと考えています。if

4

6 に答える 6

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

それTigerHippo実装して(何もする必要はありません)、次のことができます。

var cagedAnimals = new List<ICanBeHeldInZooCage>();
于 2012-10-05T12:54:59.750 に答える
4

アプローチ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、などの
メソッドが実装されていないことをお詫びします。現在のマシンにはまだVisual Studioがなく、APIを正確に覚えていません。MarkedByAttributeIsDerivedFromImplementsInterface

于 2012-10-05T13:09:49.007 に答える
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)
    {
       ....
    }

    .....

}
于 2012-10-05T12:58:43.457 に答える
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);
    }
  }

編集:

さて、これを型で行い、型をZooAnimalIに制限します。ここで、TがZooAnimalである一般的なzooクラスを作成しTました。この場合、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));
于 2012-10-05T13:01:27.390 に答える
1

人間は動物、トラは動物園にいるべき動物です。したがって、あなたの場合、Tigerandの基本クラスをもう 1 つ作成します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());
}
于 2012-10-05T12:56:56.373 に答える
0

他のオプション:

public abstract class Animal
{
    public abstract bool IsCagable { get; }
}

そして、ネストされたクラスにそれらの動作を実装させます。

その後、Zooこのトピックの回答で主に提示されるある種のクラスは、メソッドAdd内でチェックを実行する必要があります。

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.
    }
}
于 2012-10-05T13:09:20.447 に答える