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.