【发布时间】:2018-09-17 21:30:02
【问题描述】:
我正在构建一个名为 CommandHandler 的类,该类具有 ExecuteCommand 方法,其中 Command 作为输入参数。
想法是ExcecuteCommand将检查命令名称并通过名称模式执行正确的类方法,因此当命令名称为Test时,类应该有对应的TestHandler方法。
在初始化时,我使用反射来查找所有方法并在命令名称和创建的Func<Command, Task<object>> 之间创建映射。现在我已经通过让所有方法返回Task<object> 并使用Delegate.CreateDelegate 从反射方法创建Func<Command, Task<object>> 来实现这一点,但我想清理代码并允许方法返回简单类型,如int 或Task<custom class>。
我想构建一些简单的表达式,用于简单类型将执行方法并动态执行Task.FromResult,以便类方法保持干净。对于具有特定类型结果的任务,我想创建将导致Task<object> 的表达式,因此所有内容都可以缓存为Dictionary<string, Func<Command, Task<object>>。
public class CommandHandler
{
public Dictionary<string, Func<Command, Task<object>>> methodCache = new Dictionary<string, Func<Command, Task<object>>>();
public int IntCommandHandler(Command c)
{
return 5;
}
public string StringCommandHandler(Command c)
{
return "5";
}
public Task<int> AsyncIntCommandHandler(Command c)
{
return Task.Run(() => 5);
}
public async Task<object> OldWayCommandHandler(Command c)
{
return "5";
}
private void RegisterAsyncQueryHandlers(Dictionary<string, MethodInfo> handlers)
{
var filtered = handlers.Where(h => h.Value.ReturnType == typeof(Task<object>)).ToList();
foreach (var handler in filtered)
{
methodCache.Add(handler.Key, (Func<Command, Task<object>>)Delegate.CreateDelegate(typeof(Func<Command, Task<object>>), this, handler.Value, false));
}
}
public void FillCache()
{
// Get all methods with proper pattern and pass it to RegisterAsyncQueryHandlers in dictionary of command name and MethodInfo
//RegisterAsyncQueryHandlers
}
public Task<object> ExecuteCommand(Command c)
{
return methodCache[c.Name].Invoke(c);
}
}
public class Command
{
public string Name { get; set; }
}
我没有使用表达式的经验,而且我发现的大多数示例都使用基本运算符和静态方法。也许有人可以帮助我如何建立这样的表达?
【问题讨论】:
-
我不清楚为什么需要为此使用表达式树。你不能写一个方法来接受非异步函数并返回一个任务返回委托吗?例如
return value => Task.FromResult(func(value));.
标签: c# expression-trees dynamic-invoke