Find the name of the invoked method of a Func delegate

c#, delegates, func, reflection

Solution

You need an expression to parse the method's call name, but you can introduce some kind of two-level cache: one for the actual method call (which does not expire), and one for the method's call result (which may expire).

I think, your second solution goes into the right direction; just compile the expression only once.

public static class Invoker {
    public static void Invoke(Proxy proxy, Expression<Func<Proxy,string>> online) {
        var methodName = ((MethodCallExpression)online.Body).Method.Name;

        if (IsCached(proxyName, methodName)) {
            output = GetFromCache(proxyName, methodName);
        } else {
            if (IsFuncCached(methodName)) {
                func = GetFuncFromCache(methodName);
            } else {
                func = online.Compile();
                // add func to "func cache"...
            }
            output = func(proxy);
        }
    }
}

I tried to adapt your code as an example, I hope it makes sense.

Problem

I have a simple invoker where, in order to be able to use a cache library , I need to know the name of the invoked method of an object that is a parameter of a `Func` delegate. ``` class Program { static void Main(string[] args) { var proxy = new Proxy(); Invoker.invoke(proxy, p => p.formatSomething("Dumb test")); } } public class Proxy { public string formatSomething(string input){ return String.Format("-===={0}====-", input); } } public static class Invoker { public static void invoke(Proxy proxy, Func<Proxy,string> online){ //Some caching logic that require the name of the method //invoked on the proxy (in this specific case "formatSomething") var methodName = ??; if (IsCached(proxyName, methodName)){ output = GetFromCache(proxyName, methodName); }else{ output = online(proxy); } } } ``` These are some possible (bad) solutions: Solution 1: Add a string parameter passing the method name (error prone) ``` public static class Invoker { public static void invoke(Proxy proxy, Func<Proxy,string> online, string methodName){ if (IsCached(proxyName, methodName)){ output = GetFromCache(proxyName, methodName); }else{ output = online(proxy); } } } ``` Solution 2: using `Expression` with possible performance issues. ``` public static class Invoker { public static void invoke(Proxy proxy, Expression<Func<Proxy,string>> online){ var methodName = ((MethodCallExpression)online.Body).Method.Name; if (IsCached(proxyName, methodName)){ output = GetFromCache(proxyName, methodName); }else{ output = online.Compile()(proxy); } } } ``` Solution 3: using `Expression` as another parameter (error prone). ``` public static class Invoker { public static void invoke(Proxy proxy,Func<Proxy,string> online, Expression<Func<Proxy,string>> online2){ var methodName = ((MethodCallExpression)online2.Body).Method.Name; if (IsCached(proxyName, methodName)){ output = GetFromCache(proxyName, methodName); }else{ output = online(proxy); } } } ``` Do you know any other better way to inspect and get the `methodName` the Invoker needs? NOTE: I'm not searching a caching mechanism for the online function result because I already have it. The only problem is that this cache requires the proxy `methodName` invoked in the `Func` delegate.

Original source

Related problems