[C#] 52. Reflection機能を使い方 - Variable
こんにちは。明月です。
この投稿はC#でReflection機能を使い方 - Variableに関する説明です。
以前の投稿でReflectionに関するクラスと関数を使い方に関して説明しました。
link - [C#] 50. Reflection機能を使い方 - Class
link - [C#] 51. Reflection機能を使い方 - Method
Reflectionというのはクラスや関数でソースにインスタンス生成(new)や関数を呼び出し(method())の普通の仕方ではなく、動的にReflection機能を利用して生成及び呼び出す方法という意味です。
変数も同じ意味です。特にC#にはクラスの中で変数はオブジェクト指向プログラミング(OOP)によるメンバー変数はprivateで生成することが一般的です。
しかし、仕様により強制的に変数の値を変更するかユニットテスト(NUnit)を実施する時にデバックの資料で使う場合があります。
using System;
namespace Example
{
// 例クラス
class Node
{
// メンバー変数はprivate
private int data;
// コンストラクタ
public Node(int data)
{
// コンストラクタからメンバー変数の値を格納
this.data = data;
}
// コンソール出力関数
public void Print()
{
// コンソール出力
Console.WriteLine(data);
}
}
class Program
{
static void Main(string[] args)
{
// インスタンス生成
var node = new Node(10);
// 結果は10
node.Print();
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
}
上の例は一般的なコーティングする方法でNodeクラスのインスタンスを生成する時、コンストラクタに10という値を入れてPrint関数を通ってコンソールに出力しました。
当然にMain関数にはNodeのインスタンスのメンバー変数のdataを参照することができません。コンストラクタからデータを入れること以外は値を変更するか値を取得することができなく、Print関数を通って出力だけできます。
using System;
using System.Reflection;
namespace Example
{
// 例クラス
class Node
{
// メンバ-変数はprivate
private int data;
// コンストラクタ
public Node(int data)
{
// コンストラクタからメンバー変数の値を格納
this.data = data;
}
// コンソール出力関数
public void Print()
{
// コンソール出力
Console.WriteLine(data);
}
}
class Program
{
static void Main(string[] args)
{
// インスタンス生成
var node = new Node(10);
// NodeクラスのTypeを取得
var nodeClz = typeof(Node);
// Nodeクラスのdata変数を取得(privateやprotectedタイプ | インスタンスタイプ(staticではないメンバー変数)
var field = nodeClz.GetField("data", BindingFlags.NonPublic | BindingFlags.Instance);
// インスタンスのメンバー変数の値を取得
var data = field.GetValue(node);
// コンソールに出力
Console.WriteLine(data); ;
// インスタンスメンバー変数の値を設定
field.SetValue(node, 100);
// 関数を呼び出す。
node.Print();
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
}
上の例でtypeof(Node)でNodeクラスのType構造を取得した後にdataのメンバー変数を取得しました。
そしてコンソールに出力するとメンバー変数の値が出力しました。その後、SetValueを通って値を格納してPrint関数を呼び出したら変更された値が出力されました。
ここで見るとReflectionを通って関数を取得する場合とすごく似ています。実は同じですね。
using System;
using System.Reflection;
namespace Example
{
// 例クラス
class Node
{
// プロパティ
public int Data
{
get; set;
}
}
class Program
{
static void Main(string[] args)
{
// インスタンス生成
var node = new Node();
// NodeクラスのTypeを取得
var nodeClz = typeof(Node);
// Nodeクラスのすべての変数を取得
foreach (var field in nodeClz.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
// 変数名と値を出力
Console.WriteLine($"{field.Name} = {field.GetValue(node)} ");
// 変数名にDataが含めているなら
if (field.Name.Contains("Data"))
{
// 設定
field.SetValue(node, 1000);
}
}
// nodeインスタンスのプロパティのDataを出力
Console.WriteLine(node.Data);
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
}
上の例はNodeクラスにメンバー変数がありません。ただプロパティだけあります。
でも、私がReflectionを通ってNodeクラスのメンバー変数を取得するとDataのbackingfieldというメンバー変数があります。つまり、プロパティでget、setだけで設定してコンパイルしたら自動にprivate変数が生成されることを確認できます。
つまり、プロパティだけ作成しても内部的にはprivateメンバー変数が生成してOOP規約に合わせることを確認できます。
値を設定してプロパティで値を取得すると値が変更されたことを確認できます。
ReflectionはC#のアクセス修飾子を無視してデータを取得するか設定することができます。
一般プログラムを作成する時には使うことをお勧めしないです。可読性やデータ無欠性に悪くなりますね。ただ、NUnitテストやデバックプログラムを作成する時に使ったらよいですね。
ここまでC#でReflection機能を使い方 - Variableに関する説明でした。
ご不明なところや間違いところがあればコメントしてください。
- [C#] 59. ウィンドウフォーム(Window form)にコントロール(Control)を使い方法2021/10/29 19:45:43
- [C#] 58. ウィンドウフォーム(Window form)を作成する方法、そしてウィンドウメッセージとキュー2021/10/27 20:35:44
- [C#] 57. コーティング規約2021/10/21 18:57:02
- [C#] 56. 値の初期化及び基本データ値(default)を設定する方法、そして原始データのnull処理、?と??の使い方2021/10/21 18:54:41
- [C#] 55.namespaceとusing、そしてpartialの使い方2021/10/21 18:51:39
- [C#] 54. Reflection機能を使い方 - Attribute2021/10/20 19:29:31
- [C#] 53. Reflection機能を使い方 - Propertyとevent2021/10/19 21:02:58
- [C#] 52. Reflection機能を使い方 - Variable2021/10/15 19:27:37
- [C#] 51. Reflection機能を使い方 - Method2021/10/14 18:34:21
- [C#] 50. Reflection機能を使い方 - Class2021/10/13 18:34:13
- [C#] 49. Operator(演算子)のオーバーロードを使い方2021/10/12 18:28:42
- [C#] 48. IEnumerableとIEnumerator、そしてyieldキーワード2021/10/11 19:49:33
- [C#] 47. Nugetを使い方(外部ライブラリ)とデータベース(MariaDB(Mysql))を使い方、そしてトランザクション(Transaction)2021/10/08 18:58:57
- [C#] 46. データベース(MSSQL)に接続する方法2021/10/07 18:39:58
- [C#] 45. ネットワークソケット通信(Socket)を使い方2021/10/06 19:06:25
- check2024/04/10 19:03:53
- [Java] 64.Spring bootとReactを連結する方法(Buildする方法)2022/03/25 21:02:18
- [Javascript] Node.jsをインストールしてReactを使う方法2022/03/23 18:01:34
- [Java] 63. Spring bootでcronスケジューラとComponentアノテーション2022/03/16 18:57:30
- [Java] 62. Spring bootでWeb-Filterを設定する方法(Spring Security)2022/03/15 22:16:37
- [Java] JWT(Json Web Token)を発行、確認する方法2022/03/14 19:12:58
- [Java] 61. Spring bootでRedisデータベースを利用してセッションクラスタリング設定する方法2022/03/01 18:20:52
- [Java] 60. Spring bootでApacheの連結とロードバランシングを設定する方法2022/02/28 18:45:48
- [Java] 59. Spring bootのJPAでEntityManagerを使い方2022/02/25 18:27:48
- [Java] 58. EclipseでSpring bootのJPAを設定する方法2022/02/23 18:11:10
- [Java] 57. EclipseでSpring bootを設定する方法2022/02/22 19:04:49
- [Python] Redisデータベースに接続して使い方2022/02/21 18:23:49
- [Java] Redisデータベースを接続して使い方(Jedisライブラリ)2022/02/16 18:13:17
- [C#] Redisのデータベースを接続して使い方2022/02/15 18:46:09
- [CentOS] Redisデータベースをインストールする方法とコマンドを使い方2022/02/14 18:33:07