---
# System prepended metadata

title: C# ジェネリックメソッドを 式木 により実行する 2021-09-27
tags: [ジェネリックメソッド, C#, 式木]

---

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