---
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#` `ジェネリックメソッド` `式木`