質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.95%

C#Classのpropertiesを再帰的に取得したいです。

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 4,741

score 52

こんにちは。いつもお世話になります。  

Windows10, C#, Visual Studio 2015, WPFの組み合わせで開発しています。  

次のような構造のClassのpropertiesを再帰的に取得したいです。
現在、1階層目の名前はとれました。
それぞれのpropertyのclass名をとれれば再帰的になりそうです。
しかし、p.を見てもp.Classとかは見あたりませんでした。
なにしろ階層が深いので、再帰で、最終的にtextboxのfull表記と内容を取得したいです。
class名をとる方法を教えてください。
よろしくお願いします。

namespace ApplicationWindow
{
    public class MainViewModel : ViewModel
    {
        private void getProperties()
        {
            var vm = new MainWindowViewModel();
            var message = new TransinionMessage(vm, Transition.Modal, "ShowMainWindow");
            this.Messanger.Raise(message);//windowをmodalでopen

            var strings = new List<string>();
            //ClassクラスのTypeオブジェクトを取得する
            Type t = typeof(MainWindowViewModel);

            // Propertyの一覧を取得する
            PropertyInfo[] propertyInfos = t.GetProperties();

            foreach (PropertyInfo p in propertyInfos)
            {
                //名を表示
                strings.Add(p.Name);//sub1ViewModel, sub2ViewModelを取得できる。
            }
        }
    }

    public class MainWindowViewModel : ViewModel
    {
        public MainWindowViewModel()
        {
            this.sub1ViewModel = new Sub1WindowViewModel();
            this.sub1ViewModel = new Sub1WindowViewModel();
        }

        public Sub1ViewModel sub1ViewModel { get; }
        public Sub1ViewModel sub2ViewModel { get; }
    }

    public class Sub1WindowViewModel : ViewModel
    {
        public Sub1WindowViewModel()
        {
            this.sub2Sub1ViewModel = new Sub2WindowViewModel();
            this.sub2Sub1ViewModel = new Sub2WindowViewModel();
        }

        public Sub2ViewModel sub2Sub1ViewModel { get; }
        public Sub2ViewModel sub2Sub2ViewModel { get; }
    }

    public class Sub2WindowViewModel : ViewModel
    {
        public Sub2WindowViewModel()
        {
            this.sub3Sub2Sub1ViewModel = new Sub3WindowViewModel();
            this.sub3Sub2Sub1ViewModel = new Sub3WindowViewModel();
        }

        public Sub3ViewModel sub3Sub2Sub1ViewModel { get; }
        public Sub3ViewModel sub3Sub2Sub2ViewModel { get; }
    }

    public class Sub3WindowViewModel : ViewModel
    {
        public string widthText { get; set; }
        public string heightText { get; set; }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • picko

    2016/07/25 11:30

    このapplicationというかwindowには、実際には36個のwidthTextとheightTextがあり、それぞれに値が入ります。そこで、
    main-sub1-sub2-widthtext 360
    main-sub1-sub2-heighttext 240
    のように、どのtextboxの値がいくつか、を、組で取得したい、ということです。
    言葉足らずでしたら、また追記します。

    キャンセル

  • ozwk

    2016/07/25 12:14 編集

    必ず「main-sub1-sub2-width(height)text」の四階層ですか? また、Height、Width以外のプロパティは(プロパティなら無差別に、いまは存在しなくても、)取る必要がありますか?

    キャンセル

  • picko

    2016/07/25 13:05

    今回は4階層です。下記にテストしている通りです。
    ただ、せっかくつくるなら再帰のほうがよいと感じています。
    height/width以外の値も同様です。
    今回はheight/widthのみですが、ある程度拡張できるようにしたほうがよいなーとは思っています。

    キャンセル

回答 2

checkベストアンサー

+2

こんにちは。

p.PropertyTypeで、そのメンバの型(Type)が取れるので、後は再帰的に呼び出せば良いと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/25 10:35

    うまくコメントをcodeにできませんでした。・・・。

    キャンセル

  • 2016/07/25 11:46

    Typeから追跡する場合、型情報だけしかありませんので、当然インスタンスにアクセスできません。
    つまり、インスタンス(今回の場合vmから開始)も一緒に追跡する必要か有ります。

    MainWindowViewModelのプロバティをpで枚挙してますね。
    このpとvmを用いて、そのpのインスタンスを入手します。
    この場合は、auto o=p.GetValue(vm)で、vmのプロバティpのインスタンスを獲得できると思います。
    あとは、再帰的に繰り返せば、p4のvalueもとれる筈です。

    かなり昔の記憶ですので、多少の相違があるかも知れません。その時はすいません。

    キャンセル

  • 2016/07/25 13:19

    ありがとうございます。
    おっしゃるとおり型情報に加えてインスタンスを階層を追って取得して、該当のtextboxの中身を取得できました!
    ありがとうございました。

    キャンセル

+1

こんにちは。
指定したクラスからプロパティの名前を再帰的に取得し、stringの配列にしたい、ということでよろしいでしょうか?
書いてみました。

public static IEnumerable<string> GetProperties(Type type)
{
    var props = type.GetProperties();
    return props.Select(p => p.Name)
        .Concat(props.SelectMany(p => GetProperties(p.PropertyType)));
}


GetProperties(typeof(MainWindowViewModel));で呼び出してください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/25 10:41

    ありがとうございます。

    IEnumerable<string> allproperties = GetProperties(typeof(MainWindowViewModel));

    として列挙できることを確認しました。
    再帰、とてもsimpleできれいなコードです。

    しかしながら、ほしいのは、
    最終的にtextboxのfull表記と内容を取得したいです。
    なのです。

    まだこれだと、内容をとれてないです。
    もう少しお付き合いいただけないでしょうか。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.95%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る