こんにちは。明月です。
この投稿はC#でReflection機能を使い方 - Classに関する説明です。
Reflection機能とはインスタンスを動的で割り当てするか関数やフィールドおよび属性を動的に呼び出せる機能だという説明になっています。
link - https://docs.microsoft.com/
この説明は難しいですね。インスタンスを動的で割り当てするというのは我々がクラスのインスタンスを生成する時には普通はnewというキーワードを使います。
using System;
namespace Example
{
// 例クラス
class Node
{
// プロパティ
public int Data { get; set; }
// コンソールに出力する関数
public void Print()
{
// コンソールに出力
Console.WriteLine(Data);
}
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// インスタンス生成
Node node = new Node();
// プロパティにデータを入力
node.Data = 10;
// コンソールに出力する関数を呼び出す。
node.Print();
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
クラスのインスタンスは基本的にnewを利用して生成するというのは、以前に十分に説明しました。
link - [C#] 11. インスタンスう生成(new)とメモリ割り当て(StackメモリとHeapメモリ)そしてヌル(null)
インスタンスを生成する時、ソースにnew Nodeという作成します。Reflectionにはこれを静的の表現と言います。
つまり、データや分岐により他のインスタンスを生成したいならifを使ってソースを作成しなければならないです。
using System;
namespace Example
{
// インターフェース
interface INode
{
// 抽象関数
void Print();
}
// 例クラス
class Node1 : INode
{
// コンソールに出力する関数
public void Print()
{
// コンソールに出力
Console.WriteLine("Node1");
}
}
// 例クラス
class Node2 : INode
{
// コンソールに出力する関数
public void Print()
{
// コンソールに出力
Console.WriteLine("Node2");
}
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// 任意のデータ
string input = "Node1";
// インスタンス生成
INode node;
// 任意のデータにより分岐
if ("Node1".Equals(input))
{
// Node1クラスのインスタンス生成
node = new Node1();
}
else
{
// Node2クラスのインスタンス生成
node = new Node2();
}
// コンソールに出力する関数を呼び出す。
node.Print();
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
上の例をみればtypeという任意のデータを置いてNode1ならNode1のインスタンスを生成してその以外にはNode2のインスタンスを生成します。
でも、ここで仕様によりNode3のクラスが生成したら? ifを分岐してインスタンス生成する区間を作ることになります。もちろん、クラスをもっと生成するとMain関数がずっと修正が必要になります。
using System;
namespace Example
{
// インターフェース
interface INode
{
// 抽象関数
void Print();
}
// 例クラス
class Node1 : INode
{
// コンソールに出力する関数
public void Print()
{
// コンソールに出力
Console.WriteLine("Node1");
}
}
// 例クラス
class Node2 : INode
{
// コンソールに出力する関数
public void Print()
{
// コンソールに出力
Console.WriteLine("Node2");
}
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// Node2のTypeを取得
Type type = Type.GetType("Example.Node2");
// インスタンス生成
INode node = (INode)Activator.CreateInstance(type);
// コンソールに出力する関数を呼び出す。
node.Print();
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
このように作成するとクラスが生成してもType.GetTypeのString値によりインスタンス生成します。
また、我々がクラスのコンストラクタをprivateで生成することができます。
コンストラクタをprivateで設定をすればnewでインスタンスを生成することができません。コンストラクタが内部だけ生成することに設定したからです。代表的にシングルトンパターンがあります。
link - [Design pattern] 1-1. シングルトンパターン(Singleton pattern)
でも、Reflectionを使ったらコンストラクタをprivateに設定されてもインスタンス生成が可能です。
using System;
using System.Reflection;
using System.Linq;
namespace Example
{
// 例クラス
class Node
{
// コンストラクタをprivateに設定
private Node()
{
}
// コンソールに出力する関数
public void Print()
{
// コンソールに出力
Console.WriteLine("Node");
}
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// Node2のTypeを取得
Type type = Type.GetType("Example.Node");
// コンストラクタを取得
var constructor = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(x => x.GetParameters().Length == 0).First();
// インスタンスを生成
dynamic node = constructor.Invoke(null);
// コンソールに出力する関数を呼び出す。
node.Print();
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
GetParameters関数を使ってコンストラクタの種類を取得してLinqのwhereでパラメータがないコンストラクタを一つ取得します。取得すればInvoke関数を使ってインスタンスを生成します。
つまり、パラメータがあるコンストラクタはLinqのWhereによりパラメータの個数やタイプで取得することができるし生成も可能です。
ここまでC#でReflection機能を使い方 - Classに関する説明でした。
ご不明なところや間違いところがあればコメントしてください。
- [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
- [C#] 44. ファイル(FileInfo)とディレクトリ(DirectoryInfo)を扱い2021/10/05 19:29:34
- [C#] 43. ストリーム(Stream)とバイナリ(byte[])、エンコード(Encoding)、そしてusingを使い方とIDisposableインターフェース2021/10/04 18:33:04
- 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