[英]How to configure Autofac to resolve CQRS handlers and write its query dispatcher in a Web API project
我在Project1的 QUERY端有以下內容,主要包含接口
public interface IQueryResult {}
public interface IQuery<TResult> where TResult : IQueryResult {}
public interface IQueryHandler<TQuery, TResult>
where TQuery : IQuery<TResult>
where TResult : IQueryResult
{
Task<TResult> HandleAsync(TQuery query);
}
public class PersonQueryResult : IQueryResult
{
public string Name { get; set; }
}
public class GetPersonDetailsQuery : IQuery<PersonQueryResult>
{
public int Id { get; set; }
}
public interface IQueryDispatcher
{
Task<TResult> DispatchAsync<TQuery, TResult>(TQuery query)
where TQuery : IQuery<TResult>
where TResult : IQueryResult;
}
在第二Project2的引用哪個項目1,我有
public class GetPersonDetailsQueryHandler :
IQueryHandler<GetPersonDetailsQuery, PersonQueryResult>
{
public Task<PersonQueryResult> HandleAsync(GetPersonDetailsQuery query)
{
return Task.FromResult( new PersonQueryResult {Name = "Bamboo"});
}
}
最后一個Project 3是一個Web API項目,它只引用Project 1但不引用項目2.因此它只知道接口和命令和查詢。 我需要以一種我可以輕松做到這樣的方式來配置autofac
var query = new GetPersonDetailsQuery { Id = 1 };
var magicHappensHere = new QueryDispatcher(); //any better way?
PersonQueryResult result = magicHappensHere.Dispatch(query);
我在Project 1中擁有的IQueryDispatcher
似乎不適合上面的工作。 該接口的示例實現是開放的建議
public class QueryDispatcher : IQueryDispatcher
{
private readonly IComponentContext _context;
public QueryDispatcher(IComponentContext context)
{
this._context = context;
}
public Task<TResult> DispatchAsync<TQuery, TResult>(TQuery query) where TQuery : IQuery<TResult> where TResult : IQueryResult
{
var handler = _context.Resolve<IQueryHandler<TQuery, TResult>>();
return handler.HandleAsync(query);
}
}
我不知道如何實現的可能解決方案(A)在項目2中定義Autofac模塊,然后在Web API中掃描Project 2程序集?(B) http://docs.autofac.org/en/latest/register /registration.html#open-generic-components(C )掃描程序集並嘗試自動映射。 需要有關插入代碼的幫助
private static void ConfigureAutofac(HttpConfiguration config)
{
var builder = new ContainerBuilder();
//*************//
//what to do here?
//**************//
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterWebApiFilterProvider(config);
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
最后得到了建議的解決方案(B) http://docs.autofac.org/en/latest/register/registration.html#open-generic-components來工作。 此外,我可以確認解決方案中沒有添加對dll的引用
但是我仍然需要一種很好的方法來從API項目中調度查詢。 更直觀的東西
private static void ConfigureAutofac(HttpConfiguration config)
{
var builder = new ContainerBuilder();
//*************//
//heres what i did
//*************//
var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();
foreach (var assembly in assemblies)
{
builder.RegisterAssemblyTypes(assembly).AssignableTo<IQueryResult>().AsImplementedInterfaces();
builder.RegisterAssemblyTypes(assembly).AsClosedTypesOf(typeof(IQuery<>)).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(assembly).AsClosedTypesOf(typeof(IQueryHandler<,>)).AsImplementedInterfaces();
}
//rest of the code
}
您的Web API項目包含應用程序的組合根 ,組合根按定義引用應用程序中的所有其他程序集。 沒有引用它是沒有意義的,只是使事情復雜化。
請閱讀此q / a以獲得更詳細的討論:
許多開發人員不希望他們的[Web API]程序集依賴於DAL程序集,但這不是一個真正的問題。 不要忘記程序集是部署工件; 您將代碼拆分為多個程序集,以允許單獨部署代碼。 另一方面,架構層是邏輯工件。 在同一個程序集中擁有多個層是非常可能的(也是常見的)。 在這種情況下,我們最終會在同一個Web應用程序項目中具有組合根(層)和表示層(因此在同一個程序集中)。 即使該程序集引用包含DAL的程序集,表示層仍然不引用數據訪問層。 這是一個很大的區別。 當然,當我們這樣做時,我們失去了編譯器在編譯時檢查這個架構規則的能力,但這應該不是問題。 大多數架構規則實際上都不能由編譯器檢查,並且總是有類似常識的東西。 如果您的團隊中沒有常識,您可以隨時使用代碼審查(每個團隊都應該IMO總是這樣做)。 您還可以使用NDepend(商業版)等工具,它可以幫助您驗證架構規則。
通常,只有在具有插件模型的情況下,才能防止從組合根到其他程序集的硬引用,其中程序集在編譯時是未知的,並且可以在部署期間或之后添加。 然而,這些類型的場景對於LOB應用程序來說並不常見。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.