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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

3回答

4597閲覧

入れ子クラスのプライベートメンバを取得したい

kazuya_

総合スコア78

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2017/06/01 06:17

入れ子クラスがプライベートでそのプライベートメンバ(TabPageInfoの
Visibleメンバ )をとりたいです。
クラスの構造は変更できません。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Reflection; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace ClassTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public class TabPageM { private class TabPageInfo { public TabPage TabPage; public bool Visible; public TabPageInfo(TabPage page, bool v) { TabPage = page; Visible = v; } } private TabPageInfo[] _tabP = null; private TabControl _tabC = null; public TabPageM(TabControl crl) { _tabC = crl; _tabP = new TabPageInfo[_tabC.TabPages.Count]; for (int i = 0; i < _tabC.TabPages.Count; i++) _tabP[i] = new TabPageInfo(_tabC.TabPages[i], true); } } private void button1_Click(object sender, EventArgs e) { TabControl tabControl; tabControl = new TabControl(); tabControl.TabPages.Add("1"); tabControl.TabPages.Add("2"); tabControl.TabPages.Add("3"); PrivateObject po = new PrivateObject(typeof(TabPageM), new object[] { tabControl }); //型が決められない var Ta = po.GetFieldOrProperty("_tabP"); //Taが配列のため下記でvisibleプロパティをとれない Type t = Ta.GetType(); FieldInfo[] fields = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); //_tabPクラスの Visibleプロパテイをとりたい } } } コード

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2017/06/01 06:21

コード見る限りVisibleはpublicなんですが、どっちが正しいんですか?
workaholist

2017/06/01 06:40

TabPageMインスタンスの_tabPフィールドのVisibleプロパティが見たいんじゃないですか。_tabPはprivateだからVisibleプロパティが見えないんじゃなくて_tabPが見えないって話だと思います。
guest

回答3

0

ベストアンサー

PrivateObject は使ったことがないのでReflectionだけでやると以下のような感じになります。

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading.Tasks; 9using System.Windows.Forms; 10using System.Reflection; 11 12 13namespace WindowsFormsApp2 14{ 15 public partial class Form1 : Form 16 { 17 public Form1() 18 { 19 InitializeComponent(); 20 } 21 22 public class TabPageM 23 { 24 private class TabPageInfo 25 { 26 public TabPage TabPage; 27 public bool Visible; 28 public TabPageInfo(TabPage page, bool v) 29 { 30 TabPage = page; 31 Visible = v; 32 } 33 } 34 private TabPageInfo[] _tabP = null; 35 36 private TabControl _tabC = null; 37 38 public TabPageM(TabControl crl) 39 { 40 _tabC = crl; 41 _tabP = new TabPageInfo[_tabC.TabPages.Count]; 42 for (int i = 0; i < _tabC.TabPages.Count; i++) 43 _tabP[i] = 44 new TabPageInfo(_tabC.TabPages[i], true); 45 } 46 } 47 48 private void button1_Click(object sender, EventArgs e) 49 { 50 TabControl tabControl; 51 tabControl = new TabControl(); 52 tabControl.TabPages.Add("1"); 53 tabControl.TabPages.Add("2"); 54 tabControl.TabPages.Add("3"); 55 var obj =new TabPageM(tabControl); 56 57 var t = obj.GetType(); 58 var f = t.GetField("_tabP", BindingFlags.NonPublic | 59 BindingFlags.Instance); 60 object[] tabP = (object[])f.GetValue(obj); 61 var tp = tabP[0].GetType(); 62 var fp = tp.GetField("Visible"); 63 64 MessageBox.Show("Visible0:" + (bool)fp.GetValue(tabP[0])); 65 MessageBox.Show("Visible1:" + (bool)fp.GetValue(tabP[1])); 66 MessageBox.Show("Visible2:" + (bool)fp.GetValue(tabP[2])); 67 } 68 } 69} 70

投稿2017/06/01 11:18

hmmm

総合スコア818

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

TabPageInfoクラスはTabPageMクラスのprivate classなのでForm1からはクラス自体がアクセスできないですね。よってForm1の文脈において_tabPをreflectionでとってきたとしても、それをTabPageInfoクラスとして扱うことができません。

一応dynamicを使って「どのクラスなんだけかわからないけど多分Visibleっていうboolのフィールドがあるはず」というようなコーディングはできますが、上のコードのように「まさにその文脈から見えているクラスにもかかわらずdynamicを使ってしかアクセスできない」のは奇妙に見えます。つまり内部クラスの定義の仕方に問題があるように思えます。

クラス構造を変更できない

設計を見直し、button1_Click内部で現在やろうとしている処理の中でTabPageMが担当すべきものを分離し、それをTabPageM内へ実装した上でForm1#button_Clickからそれを呼び出すのが素直な解決法であるように思えますが、クラス構造を変更できないということが「TabPageMのアクセス修飾子を含めて実装に一切手を加えられない」ということならreflectionとdynamicなどを組み合わせるしかなさそうです。

C#

1FieldInfo fi = ... 2dynamic tabPageInfo = fi.GetValue(...); 3bool visible = tagPageInfo.Visible;

投稿2017/06/01 09:21

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuya_

2017/06/02 02:09

ありがとうございました。アクセスするところまでは、いけましたが、最後のリフレクションの使用方法がわかりませんでした。
guest

0

こんにちは。

入れ子クラスがプライベートでそのプライベートメンバ(TabPageInfoの

Visibleメンバ )をとりたいです。

パブリックメンバの間違いですね?(コードではVisibleはpublicになってます。)

まず、現状のままでも、TabPageMからTabPageInfoのVisibleにはアクセス出来るはずです。

クラスの構造は変更できません。

これの意味次第ですが、TabPageMにpublicなメソッドを追加できるなら、必要なTabPageInfoのVisibleにアクセスするメソッドを書けば良いです。
でも、このコードをメンテナンスしている人に確認するべきです。将来的にアクセスされると困るような変数だと危険な行為です。(privateって、将来変更する可能性があるからアクセスしないでねと言う積極的な意味が込められていることもありますから。)

もし、TabPageMを一切変更してはいけないというルールがあるなら、ルールを破らない限り無理です。でも、普通はTabPageMの設計担当者は変更可でしょうから、その人に変更依頼するのが正攻法と思います。

投稿2017/06/01 08:09

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuya_

2017/06/02 02:10

ありがとうございました。クラスは全く変更できません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問