Dav*_*bot 2 c# generics cqrs simple-injector
基于这篇精彩的CQRS文章,我定义了以下接口:
public interface IQuery<TResult>
{
}
public interface IQueryHandler<TQuery, TResult> where TQuery : IQuery<TResult>
{
    TResult Handle(TQuery query);
}
实现通用异步QueryHandler的最佳方法是什么?到目前为止,我有一个新的接口定义来将Handle()方法更改为void并接受新的"Complete"事件处理程序.就像是:
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
    });
}
你不需要做任何事情.回来Task<T>:
public class FindUsersBySearchTextQuery : IQuery<Task<User[]>>
{
}
public class FindUsersBySearchTextQueryHandler
    : IQueryHandler<FindUsersBySearchTextQuery, Task<User[]>>
{
    public async Task<User[]> Handle(FindUsersBySearchTextQuery query)
    {
        // ...
    }
}
Task<T>是.NET 4.0的一部分,所以你可以使用它.您可以使用C#5.0,这允许您使用新的async/await关键字,这使编程更容易.如果这不可用,您仍然可以使用.NET 4.0中的TPL API来实现这一点.
另一方面,如果您确定所有查询始终是异步的,则可以将界面更改为以下内容:
public interface IQuery<TResult> { }
public interface IQueryHandler<TQuery, TResult> where TQuery : IQuery<TResult>
{
    // Note the Task<T> here
    Task<TResult> Handle(TQuery query);
}
这种方法通常更好,因为现在您可以从查询定义中移出有关事物是否异步的知识.查询定义(例如class FindUsersBySearchTextQuery : IQuery<User[]>)应该只关心返回哪些数据,sonmething是异步是否是一个实现细节(不幸的是它是一个实现细节感染您的调用堆栈,如病毒,但仍然是一个实现细节).
| 归档时间: | 
 | 
| 查看次数: | 725 次 | 
| 最近记录: |