Pregunta

Me gustaría obtener el nombre del método que se delega como Func.

Func<MyObject, object> func = x => x.DoSomeMethod();
string name = ExtractMethodName(func); // should equal "DoSomeMethod"

¿Cómo puedo lograr esto?

- Para alardear de derechos -

Haga que ExtractMethodName también funcione con una invocación de propiedad, haciendo que devuelva el nombre de la propiedad en esa instancia.

ej.

Func<MyObject, object> func = x => x.Property;
string name = ExtractMethodName(func); // should equal "Property"
¿Fue útil?

Solución

¡Mira mamá! ¡Sin árboles de expresión!

Aquí hay una versión rápida, sucia y específica de la implementación que toma el token de metadatos del flujo IL del lambda subyacente y lo resuelve.

private static string ExtractMethodName(Func<MyObject, object> func)
{
    var il = func.Method.GetMethodBody().GetILAsByteArray();

    // first byte is ldarg.0
    // second byte is callvirt
    // next four bytes are the MethodDef token
    var mdToken = (il[5] << 24) | (il[4] << 16) | (il[3] << 8) | il[2];
    var innerMethod = func.Method.Module.ResolveMethod(mdToken);

    // Check to see if this is a property getter and grab property if it is...
    if (innerMethod.IsSpecialName && innerMethod.Name.StartsWith("get_"))
    {
        var prop = (from p in innerMethod.DeclaringType.GetProperties()
                    where p.GetGetMethod() == innerMethod
                    select p).FirstOrDefault();
        if (prop != null)
            return prop.Name;
    }

    return innerMethod.Name;
}

Otros consejos

No creo que esto sea posible en el caso general. ¿Qué pasaría si tuvieras:

Func<MyObject, object> func = x => x.DoSomeMethod(x.DoSomeOtherMethod());

¿Qué esperarías?

Dicho esto, puedes usar la reflexión para abrir el objeto Func y ver qué hace dentro, pero solo podrás resolverlo en ciertos casos.

Mira mi respuesta de pirateo aquí:

¿Por qué no hay un `fieldof Operador `o` methodof` en C #?

En el pasado lo hice de otra manera que usaba Func en lugar de Expression<Func<...>>, pero estaba mucho menos satisfecho con el resultado. El MemberExpression utilizado para detectar el campo en mi método fieldof devolverá un PropertyInfo cuando se utiliza una propiedad.

Editar # 1: Esto funciona para un subconjunto del problema:

Func<object> func = x.DoSomething;
string name = func.Method.Name;

Edición n. ° 2: Quien me haya marcado debe tomarse un segundo para darse cuenta de lo que está sucediendo aquí. Los árboles de expresión pueden usarse implícitamente con expresiones lambda y son la forma más rápida y confiable de obtener la información solicitada específica aquí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top