c# - Autofac 按上下文解析
问题描述
因此,我基本上计划从 RavenDb 切换到 MongoDb,并对我的存储库进行不同的实现。我将 CQRS 与消息调度程序一起使用,我希望使用两组存储库运行我的消费者两次
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Consumers.IMessageConsumer<>))).AsClosedTypesOf(typeof(Consumers.IMessageConsumer<>));
builder.RegisterType<RavenUserRepository>().As<IUserRepository>().InstancePerLifetimeScope();
builder.RegisterType<MongoUserRepostiory>().As<IUserRepository>().InstancePerLifetimeScope();
public Task Dispatch<TMessage>(TMessage message) where TMessage : IMessage
{
// Raven
using (var scope = _lifetimeScope.BeginLifetimeScope())
{
var consumer = scope.Resolve<IMessageConsumer<TMessage>>();
consumer.Handle(message, CancellationToken.None);
}
// Mongo
using (var scope = _lifetimeScope.BeginLifetimeScope())
{
var consumer = scope.Resolve<IMessageConsumer<TMessage>>();
consumer.Handle(message, CancellationToken.None);
}
return Task.CompletedTask;
}
所以我基本上想告诉每个生命周期范围它允许使用哪些存储库。我正在撞砖墙,但似乎无法解决
解决方案
这种场景在此处被大量记录: https ://autofaccn.readthedocs.io/en/latest/faq/select-by-context.html 。根据您的整体方法,您可以选择很多选项,例如在您过渡时是否支持两个回购只是一个短期解决方案。
使用该方法的解决方案之一的示例如下Keyed
。如果我们在 repo 注册中添加一个密钥:
public enum RepoType
{
Raven,
Mongo
}
...
builder.RegisterType<RavenUserRepository>().Keyed<IUserRepository>(RepoType.Raven).InstancePerLifetimeScope();
builder.RegisterType<MongoUserRepostiory>().Keyed<IUserRepository>(RepoType.Mongo).InstancePerLifetimeScope();
而不是
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Consumers.IMessageConsumer<>))).AsClosedTypesOf(typeof(Consumers.IMessageConsumer<>));
我们有
builder.RegisterGeneric(typeof(MessageConsumer<>))
.Keyed(RepoType.Mongo, typeof(IMessageConsumer<>)).WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IUserRepository),
(pi, ctx) => ctx.ResolveKeyed<IUserRepository>(RepoType.Mongo)));
builder.RegisterGeneric(typeof(MessageConsumer<>))
.Keyed(RepoType.Raven, typeof(IMessageConsumer<>))
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IUserRepository),
(pi, ctx) => ctx.ResolveKeyed<IUserRepository>(RepoType.Raven)));
最后一部分不是最漂亮的,但对于每个 repo,它基本上是在说“IConsumer<>
用一个密钥注册一个,它在内部使用IUserRepository
相同的密钥解析”。然后,我们可以IConsumer<>
根据使用代码的需要解析 s ,或者作为IEnumerable<>
(如果您有多个服务注册,这将自动从 Autofac 获得)或单独使用我们的密钥:
var consumers = scope.Resolve<IEnumerable<IMessageConsumer<T>>>();
foreach (var messageConsumer in consumers)
{
messageConsumer.Handle(message, CancellationToken.None);
}
或者
var mongoConsumer = scope.ResolveKeyed<IMessageConsumer<T>>(RepoType.Mongo);
mongoConsumer.Handle(message, CancellationToken.None);
var ravenConsumer = scope.ResolveKeyed<IMessageConsumer<T>>(RepoType.Raven);
ravenConsumer.Handle(message, CancellationToken.None);
推荐阅读
- r - R中的转置和求和不同的值
- ios - 如何从 iOS 应用程序向 Apple Carplay 发送通知
- d3.js - 如何使 svg 符号投影
- kubernetes - Google FileStore 是否适用于 GKE 上的 Windows 容器?
- amazon-redshift - 首次运行查询的 Redshift 编译时间
- sql - 使用新列将主键从简单更改为复合
- sql-server - 通过 .NET 应用程序中的 SqlCommand 的临时表
- c# - 如何删除日期字段中的时间格式(Json 数据)
- python - 熊猫数据框多列条形图
- javascript - 当 API 调用后的 setState 时反应不重新渲染