「C#」ジェネリック関数で引数ありコンストラクタを呼ぶコード

#前書き
C# 7.3でジェネリックを使って引数のあるコンストラクターを呼ぶ
コードを考えてみました

#コード

``` csharp
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Linq.Expressions;

namespace Sample {
	static class Test {
		static void Main() {
			Console.WriteLine("\n直接、引数ありコンストラクタを呼ぶ");
			Console.WriteLine(ObjA.New(0, 1, 2));
			Console.WriteLine(ObjB.New(3, 4, 5));

			Console.WriteLine("\nジェネリックメソッドで引数ありコンストラクタを呼ぶ");
			Console.WriteLine(CreateObjBase<ObjA>(0, 1, 2));
			Console.WriteLine(CreateObjBase<ObjB>(3, 4, 5));
		}

		//引数ありコンストラクターを呼ばせるジェネリックで関数
		static T CreateObjBase<T>(int id1, int id2, int id3) where T : ObjBase {
			var maker = NewObjectHelper<T>.CreateMethod<Func<int, int, int, T>>();

			return maker(id1, id2, id3);
		}
	}

	//TInstanceに戻り値の型を指定
	static class NewObjectHelper<TInstance> {
		//使うFunc型から引数の型だけ抜き出す
		static Type[] CreateParameterType<TFunc>() where TFunc : Delegate {
			//Type.GetGenericArguments()で
			//ジェネリック型に指定された型を全て取り出せる
			var method_use_types = new List<Type>(typeof(TFunc).GetGenericArguments());
			
			//使うFunc型の戻り値の型だけ除外
			var deleteIndex = method_use_types.FindIndex((i) => i == typeof(TInstance));
			method_use_types.RemoveAt(deleteIndex);

			return method_use_types.ToArray();
		}
		//Type配列から式木用の配列を作成
		static List<ParameterExpression> CreateParamsListFromTypes(Type[] types) {
			var paramList = new List<ParameterExpression>(types.Length);

			foreach (var i in types) paramList.Add(Expression.Parameter(i));

			return paramList;
		}

		//式木を使ってコンストラクタを呼ぶ関数を作成
		public static TFunc CreateMethod<TFunc>() where TFunc : Delegate {
			var argsType = CreateParameterType<TFunc>();
			var paramList = CreateParamsListFromTypes(argsType);
			var flag = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;

			var constructor = typeof(TInstance).GetConstructor(flag,
				Type.DefaultBinder,
				argsType,
				null
			);

			return Expression.Lambda<TFunc>(
				Expression.New(
					constructor, paramList),
				paramList).Compile();
		}
		//式木を使ってコンストラクタを呼ぶ関数を作成
		//
		//引数のtypeValueで戻り値の型推論をさせる
		public static TFunc CreateMethod<TFunc>(TFunc typeValue) where TFunc : Delegate {
			var argsType = CreateParameterType<TFunc>();
			var paramList = CreateParamsListFromTypes(argsType);
			var flag = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;

			var constructor = typeof(TInstance).GetConstructor(flag,
				Type.DefaultBinder,
				argsType,
				null
			);

			return Expression.Lambda<TFunc>(
				Expression.New(
					constructor, paramList),
				paramList).Compile();
		}
	}

	//テスト用クラス
	abstract class ObjBase {
		public int Id1;
		public int Id2;
		public int Id3;

		public override string ToString() {
			return  "[" + Id1 + " : " + Id2 + " : " + Id3 + "]";
		}
	}
	sealed class ObjA : ObjBase {
		public static Func<int, int, int, ObjA> New { get; } = NewObjectHelper<ObjA>.CreateMethod(New);

		ObjA(int id1, int id2, int id3) {
			Id1 = id1;
			Id2 = id2;
			Id3 = id3;
		}

		public override string ToString() {
			return nameof(ObjA) + " " + base.ToString();
		}
	}
	sealed class ObjB : ObjBase {
		public static Func<int, int, int, ObjB> New { get; } = NewObjectHelper<ObjB>.CreateMethod(New);

		ObjB(int id1, int id2, int id3) {
			Id1 = id1;
			Id2 = id2;
			Id3 = id3;
		}

		public override string ToString() {
			return nameof(ObjB) + " " + base.ToString();
		}
	}
}
```

#注意点
コンストラクタがpublicでなくても呼び出せてしまう
引数の型や数を間違えてもコンパイルエラーが出ない