読者です 読者をやめる 読者になる 読者になる

Strong-typed reflection / Act Cadenza

.NET

原稿に収録できるか分からないのでソースだけ載っけておきます.解説はまあ載らないことが確定したときにでも.
元ネタは Daniel Cazzulino の strong-typed reflection および id:NyaRuRu:20061129:p1

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

public static class Reflector
{
    static MethodInfo GetMethodInfo(this Expression expression)
    {
        var findfunc = null as Func<Expression, MethodInfo>;
        findfunc = expr =>
        {
            switch (expr.NodeType)
            {
                case ExpressionType.Lambda:
                    return findfunc((expr as LambdaExpression).Body);
                case ExpressionType.Quote:
                    return findfunc((expr as UnaryExpression).Operand);
                case ExpressionType.Call:
                    var mce = expr as MethodCallExpression;
                    return mce != null ? mce.Method : null;
                case ExpressionType.MemberAccess:
                    var me = expr as MemberExpression;
                    var pi = me.Member as PropertyInfo;
                    return pi != null ? pi.GetGetMethod(true) : null;
                default:
                    return null;
            }
        };

        return findfunc(expression);
    }
    public sealed class Function<TResult>
    {
        public static MethodInfo Bind(
            Expression<Func<Expression<Func<TResult>>>> expr)
        {
            return expr.GetMethodInfo();
        }
        public static MethodInfo Bind<TArg0>(
            Expression<Func<TArg0, Expression<Func<TResult>>>> expr)
        {
            return expr.GetMethodInfo();
        }
        public static MethodInfo Bind<TArg0, TArg1>(
            Expression<Func<TArg0, TArg1, Expression<Func<TResult>>>> expr)
        {
            return expr.GetMethodInfo();
        }
        public static MethodInfo Bind<TArg0, TArg1, TArg2>(
            Expression<Func<TArg0, TArg1, TArg2, Expression<Func<TResult>>>> expr)
        {
            return expr.GetMethodInfo();
        }
    }
    public sealed class Function
    {
        public static MethodInfo Bind<TArg0>(
            Expression<Func<TArg0, Expression<Action>>> expr)
        {
            return expr.GetMethodInfo();
        }
        public static MethodInfo Bind<TArg0, TArg1>(
            Expression<Func<TArg0, TArg1, Expression<Action>>> expr)
        {
            return expr.GetMethodInfo();
        }
        public static MethodInfo Bind<TArg0, TArg1, TArg2>(
            Expression<Func<TArg0, TArg1, TArg2, Expression<Action>>> expr)
        {
            return expr.GetMethodInfo();
        }
        public static MethodInfo Bind<TArg0, TArg1, TArg2, TArg3>(
            Expression<Func<TArg0, TArg1, TArg2, TArg3, Expression<Action>>> expr)
        {
            return expr.GetMethodInfo();
        }
    }
}

使い方はこんな感じ.

// DateTime.get_Now : () -> DateTime
var mi1 = Reflector.Function<DateTime>.Bind(
    () => () => DateTime.Now);

// Array.Sort<T>(T[]) : int[] -> ()
var mi2 = Reflector.Function.Bind(
    (int[] array) => () => Array.Sort(array));

// string.EndsWith(string) : (string -> ) string -> bool
var mi3 = Reflector.Function<bool>.Bind(
    (string s1, string s2) => () => s1.EndsWith(s2));