【发布时间】:2015-02-20 16:45:54
【问题描述】:
我有一个简单的调用程序,为了能够使用缓存库,我需要知道作为Func 委托参数的对象的调用方法的名称。
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);
}
}
}
这些是一些可能的(坏的)解决方案:
解决方案一:添加一个字符串参数传递方法名(容易出错)
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);
}
}
}
解决方案 2: 使用 Expression 可能会出现性能问题。
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);
}
}
}
解决方案 3: 使用 Expression 作为另一个参数(容易出错)。
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);
}
}
}
您知道其他更好的方法来检查和获取 Invoker 所需的 methodName 吗?
注意:
我没有为在线函数结果搜索缓存机制,因为我已经有了它。
唯一的问题是这个缓存需要在Func委托中调用的代理methodName。
【问题讨论】:
-
我很确定这不会像书面的那样工作,一旦你得到委托就结束了。但是,您可以改为传入
Expression<>,并在调用程序中处理编译。然后你可以自己解析Expression<>树,得到函数名。 -
除了使用
Expression<Func<T>>之外,这是无法做到的,只能反编译代码并尝试弄清楚它的作用。如果委托调用两个方法怎么办?你怎么知道你想要哪一个? -
给定您的示例(没有捕获值),委托实例将被缓存并且始终相同。您可能应该为此使用一个哈希表,如果没有,仍然使用一个但构造一个更好的哈希/等于实现。
-
为什么要调用一些缓存逻辑然后调用func呢?
标签: c# reflection delegates func