はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【C#】privateコンストラクタしかないclassを無理やりリフレクションで生成する

はじめに

今回はPrivateコンストラクタしかないclassを無理やりリフレクションで作成する方法を紹介したいと思います。

public class Hoge
{
    // privateコンストラクタしかないと正攻法だと外から生成できない
    private Hoge()
    {
        
    }
}

やり方

引数がない場合

Activator.CreateInstancenonPublicがあるオーバーロードを利用することで実現できます。

public static object? CreateInstance (Type type, bool nonPublic);

learn.microsoft.com

// サンプル
public class Sample
{
    public static void Main(string[] args)
    {
        // NG: var hoge = new Hoge();
        
        // 引数のnonPublicをtrueにするのがキモ
        var hoge = (Hoge)Activator.CreateInstance(typeof(Hoge), nonPublic: true);
        
        hoge.Execute();
    }
}

public class Hoge
{
    // privateコンストラクタしかないと正攻法だと外から生成できない
    private Hoge() { }

    public void Execute() => Console.WriteLine("Hello, World!");
}

引数がある場合

コンストラクタに引数がある場合はbindingAttrargsが引数にあるCreateInstanceメソッドを利用します。

public static object? CreateInstance (Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture);

Activator.CreateInstance メソッド (System) | Microsoft Learn

public class Sample
{
    public static void Main(string[] args)
    {
        // NG: var hoge = new Hoge("Hello, World", "text2");
        
        // 引数bindingAttrに以下のBindingFlagsを渡し、argsに引数を渡す
        BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
        var hoge = (Hoge)Activator.CreateInstance(typeof(Hoge), bindingAttr, null, ["Hello, World", "text2"], null);
        
        hoge.Execute();
    }
}

public class Hoge
{
    private readonly string _text;
    
    // privateコンストラクタしかないと正攻法だと外から生成できない
    private Hoge(string text, string text2)
    {
        _text = text;
    }

    public void Execute() => Console.WriteLine(_text);
}