Почему в С# нет оператора `fieldof` или` methodof`?

Их можно использовать следующим образом:

FieldInfo field = fieldof(string.Empty);
MethodInfo method1 = methodof(int.ToString);
MethodInfo method2 = methodof(int.ToString(IFormatProvider));

fieldof может быть скомпилирован в IL как:

ldtoken <field>
call FieldInfo.GetFieldFromHandle

methodof может быть скомпилирован в IL как:

ldtoken <method>
call MethodBase.GetMethodFromHandle

Всякий раз, когда используется оператор typeof, вы получаете идеальные результаты поиска "Все ссылки". К сожалению, как только вы отправляетесь на поля или методы, вы оказываетесь в неприятных хаках. Я думаю, вы могли бы сделать следующее... или вы можете вернуться к получению поля по имени.

public static FieldInfo fieldof<T>(Expression<Func<T>> expression)
{
    MemberExpression body = (MemberExpression)expression.Body;
    return (FieldInfo)body.Member;
}

public static MethodInfo methodof<T>(Expression<Func<T>> expression)
{
    MethodCallExpression body = (MethodCallExpression)expression.Body;
    return body.Method;
}

public static MethodInfo methodof(Expression<Action> expression)
{
    MethodCallExpression body = (MethodCallExpression)expression.Body;
    return body.Method;
}

public static void Test()
{
    FieldInfo field = fieldof(() => string.Empty);
    MethodInfo method1 = methodof(() => default(string).ToString());
    MethodInfo method2 = methodof(() => default(string).ToString(default(IFormatProvider)));
    MethodInfo method3 = methodof(() => default(List<int>).Add(default(int)));
}

Ответ 1

Эрик Липперт (в команде разработчиков С#) имеет отличный обзор/обсуждение по этой теме здесь. Цитировать:

Его удивительная особенность, которую почти все, кто участвует в процессе проектирования, хотел бы сделать, но есть хорошие практические причины, по которым мы не хотим этого делать. Если наступает день, когда он разрабатывается и реализуется, это лучший способ, которым мы могли бы потратить наш ограниченный бюджет, хорошо сделайте это. До тех пор используйте Reflection.

Ответ 2

Вы можете избежать использования как отражения, так и lambdas (.NET Framework 2.0). Рассмотрим следующий класс:

public class methodof<T>
{
    private MethodInfo method;

    public methodof(T func)
    {
        Delegate del = (Delegate)(object)func;
        this.method = del.Method;
    }

    public static implicit operator methodof<T>(T methodof)
    {
        return new methodof<T>(methodof);
    }

    public static implicit operator MethodInfo(methodof<T> methodof)
    {
        return methodof.method;
    }
}

и его использование:

MethodInfo writeln = (methodof<Action>)Console.WriteLine;
MethodInfo parse = (methodof<Func<string, int>>)int.Parse;

Ответ 3

@280Z28 - Мы просто сидели, чтобы понять, как это сделать, когда я нашел ваш вопрос и код. Нам нужен был метод PropertyOf, поэтому я добавил его. Здесь это на тот случай, если кому-то это понадобится. спасибо за большой вопрос.

     public static PropertyInfo PropertyOf<T>(Expression<Func<T>> expression)
    {
        MemberExpression body = (MemberExpression)expression.Body;
        PropertyInfo pi = body.Member as PropertyInfo;
        if (pi != null)
        {
            return pi;
        }
        else throw new ArgumentException("Lambda must be a Property.");
    } 

      [TestMethod()]
    public void MethodofPropertyOfTest<T>()
    {

        string foo = "Jamming";
        MethodInfo method1 = ReflectionHelper.Methodof(() => default(string).ToString());
        PropertyInfo prop = ReflectionHelper.PropertyOf(() => default(string).Length);
        Assert.AreEqual(method1.Invoke(foo, null), "Jamming");
        Assert.AreEqual(prop.GetGetMethod().Invoke(foo, null), foo.Length);
    }

Ответ 4

это версия общего типа, которая может использовать F2 для переименования и не нуждается в модификации существующего кода в этом примере имя метода - GetPKValue

var typFactory = typeof(FormFieldFactory<>).MakeGenericType(entity.GetType());
var methodName = new Func<object, object>(FormFieldFactory<object>.GetPKValue).Method.Name;

var theMethod =
    (Func<object, object>)Delegate.CreateDelegate(
        typeof(Func<object, object>)
        , typFactory.GetMethod(methodName)
    );

Ответ 5

Я вспоминаю день, когда размышление становится таким легким. Если вы считаете, что динамический SQL был плохим, это привело бы к чему-то еще в десятки раз.

Представьте себе, изменив имя свойства и вам придется беспокоиться о ошибках времени выполнения./Дрожь