指定した型を継承した型の一覧を取得する
子孫一覧。
成果物
情報源
- http://baba-s.hatenablog.com/entry/2014/06/10/200710
- https://docs.microsoft.com/ja-jp/dotnet/api/system.type?view=netcore-3.0
きっかけ
こちらでインタフェース継承クラス一覧を取得できると知った。ならば継承クラスを一覧するにはどうすればいいの? と思ったのがきっかけ。
コード
class Program { static void Main(string[] args) { Console.WriteLine("Aの子のみ"); foreach (var t in AssemblyUtils.GetChildren<A>()) {Console.WriteLine($"{t}");} Console.WriteLine(); Console.WriteLine("Aの子孫すべて"); foreach (var t in AssemblyUtils.GetInheritanceTypes<A>()) {Console.WriteLine($"{t}");} Console.WriteLine(); Console.WriteLine("Aの末裔すべて"); foreach (var t in AssemblyUtils.GetEndInheritanceTypes<A>()) {Console.WriteLine($"{t}");} } }
class A {} class A1 : A {} class A2 : A {} class A11 : A1 {} class B {} class B1 : B {}
public static class AssemblyUtils { // 指定した型を継承した子型を返す。(直下の子のみ。子孫以下であっても対象外) public static Type[] GetChildren<T>() { return Assembly.GetExecutingAssembly().GetTypes().Where(c => c.BaseType == typeof(T)).ToArray(); } // 指定した型を継承した子孫型を返す。(指定した型は対象外) public static Type[] GetInheritanceTypes<T>() { return _GetInheritanceTypes<T>().ToArray(); } private static IEnumerable<Type> _GetInheritanceTypes<T>() { return Assembly.GetExecutingAssembly().GetTypes().Where(c => c.IsSubclassOf(typeof(T))); } // 指定した型の末裔を返す。(指定した型や末裔以前の型は対象外) public static Type[] GetEndInheritanceTypes<T>() { var types = _GetInheritanceTypes<T>().ToList(); for (int t1=types.Count-1; t1>=0; t1--) { for (int t2=types.Count-1; t2>=0; t2--) { if (types[t2] == types[t1].BaseType) { types.RemoveAt(t2); } } } return types.ToArray(); } }
出力結果
Aの子のみ GetInheritanceType.A1 GetInheritanceType.A2 Aの子孫すべて GetInheritanceType.A1 GetInheritanceType.A2 GetInheritanceType.A11 Aの末裔すべて GetInheritanceType.A2 GetInheritanceType.A11
クラスの継承関係は以下。
- A
- A1
- A11
- A2
- A1
- B
- B1
学習項目
型の比較
コード | 意味 |
---|---|
instance is targetType |
指定したインタフェースを実装しているか |
instance.GetType().IsSubclassOf(targetType) |
指定した型から派生した型か(同一ならfalse ) |
instance.GetType().IsAssignableFrom(targetType) |
指定した型と同じか派生した型か |
- | 指定した型を継承した末裔型か |
末裔の取得
指定した型を継承した全型のうち末裔のみ取得したい。どうやるか。
末裔は、言い換えると「指定した型を継承した全型のうち、どの型からも継承されていない型」である。
- 指定した型を継承したすべての型を取得する(
_GetInheritanceTypes
) - 上記から再帰的に
BaseType
を取得し、その一覧を返す - 1の中から2を除外し、残ったものが「どの型からも継承されていない型」である
ツリー構造になっていないため再帰的にチェックすることはできない。そこでリストをループして網羅的にチェックする。foreach
ではリストのループ中にリスト項目を削除できない。そこでfor
を使って行う。削除したときインデックスが狂わないように後ろから順にループする。
所感
できればツリー構造として返せるようにもしてみたい。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13 ※
- bash 4.4.12(1)-release ※
- SQLite 3.29.0 ※
- C# dotnet 3.0.100 ※
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux