【发布时间】:2014-08-15 10:35:15
【问题描述】:
基于this梦幻般的CQRS文章,我定义了以下接口:
public interface IQuery<TResult>
{
}
public interface IQueryHandler<TQuery, TResult> where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
实现通用异步 QueryHandler 的最佳方式是什么?到目前为止,我有一个新的接口定义来将 Handle() 方法更改为 void 并接受新的“完成”事件处理程序。比如:
public interface IQueryHandlerAsync<TQuery, TResult> where TQuery : IQuery<TResult>
{
void Handle(TQuery query, RunWorkerCompletedEventHandler complete);
}
我可以为所有实现 IQueryHandlerAsync 接口的查询处理程序创建新的具体类,例如:
public class FindUsersBySearchTextQueryHandlerAsync
: IQueryHandlerAsync<FindUsersBySearchTextQuery, User[]>
{
private readonly IQueryHandler<FindUsersBySearchTextQuery, User[]> queryHandler;
public FindUsersBySearchTextQueryHandler(IQueryHandler<FindUsersBySearchTextQuery, User[]> queryHandler)
{
this.queryHandler = queryHandler;
}
public void Handle(FindUsersBySearchTextQuery query, RunWorkerCompletedEventHandler complete)
{
var worker = new BackgroundWorker();
worker.DoWork += DoWork;
worker.RunWorkerCompleted += complete;
worker.RunWorkerAsync(query);
}
void DoWork(object sender, DoWorkEventArgs e)
{
FindUsersBySearchTextQuery query = (FindUsersBySearchTextQuery)e.Argument;
queryHandler.Handle(query);
}
}
这个 Async 具体类对于我的所有查询都非常相似。有没有办法使这个通用并且可能自动注入?
编辑:解决方案
保留接口,但更改 Handle() 方法以返回任务:
public interface IQuery<TResult> { }
public interface IQueryHandler<TQuery, TResult> where TQuery : IQuery<TResult>
{
Task<TResult> Handle(TQuery query);
}
在具体实现中,将 Handle() 方法的工作封装到一个 Task 中,启动该任务,然后返回它。
public Task<User[]> Handle(FindUsersBySearchTextQuery query)
{
return TaskEx.Run(() =>
{
//Do slow operation
//...
return new User[] { ... };
});
}
用法:
private async void GetUsers()
{
var users = await queryHandler.Handle(new FindUsersBySearchTextQuery
{
SearchText = searchText
});
}
【问题讨论】:
-
为什么不尝试使用/应用 .net 4.5 的 await/async 功能?
-
不幸的是,为了兼容 WinXP,我一直坚持使用 .NET 4.0。
-
@BoroDrummer 它将对象定义为一个查询(-definition),它将返回一个指定返回类型的对象。
标签: c# generics cqrs simple-injector