--- lang: ja-jp breaks: true --- # C# ジェネリックメソッドを 式木 により実行する 2021-09-27 ```csharp= public class RandomValueCreator { private static ConcurrentDictionary<string, Func<Type, object>> m_dicMethodExpression = new(); public static object GetRandomValue( Type type ) { object ret = null; ・・・ return ret; } public static object Invoke_GetRandomValue_HashSet( Type type ) { string fullname = type.FullName; Func<Type, object> func = null; if (m_dicMethodExpression.TryGetValue(fullname, out func) == false) { var targetParam = Expression.Parameter(typeof(Type)); MethodCallExpression methodCallExpression = Expression.Call( type : typeof(RandomValueCreator), methodName : nameof(GetRandomValue_HashSet), typeArguments : new Type[] { type }, arguments : targetParam ); Expression<Func<Type, object>> lambda = Expression.Lambda<Func<Type, object>>( // メソッドを呼ぶExpression body : methodCallExpression, // ラムダ式の引数 parameters: targetParam ); func = lambda.Compile(); m_dicMethodExpression.TryAdd(fullname, func); } ret = func(type); return ret; } public static HashSet<T> GetRandomValue_HashSet<T>(Type type) { HashSet<T> ret = new HashSet<T>(); for (int i = 0; i < 10; i++) { T value = (T)GetRandomValue(type); ret.Add(value); } } } ``` ## ジェネリックメソッドの戻り値が Enum 型場合は、`Expression.Convert` を使用してobject型にキャストする必要がある。 ```csharp= Expression<Func<Type, object>> lambda = Expression.Lambda<Func<Type, object>>( // メソッドを呼ぶExpression body : Expression.Convert(methodCallExpression, typeof(object)), // ラムダ式の引数 parameters : targetParam ); ``` ###### tags: `C#` `ジェネリックメソッド` `式木`