使用 NServicebus 实现 Autofac 的先有鸡还是先有蛋问题
Chicken and egg issue implementing Autofac with NServicebus
背景
我正在尝试设置需要与 NServicebus 端点通信的 Web API 2。
我需要实现 IoC,这将使用 Autofac 完成。
我有什么
控制器定义如下:
[RoutePrefix("api")]
public class Controller : ApiController
{
private IEndpointInstance EndpointInstance { get; set; }
public public MyController(IEndpointInstance endpointInstance)
{
this.EndpointInstance = endpointInstance;
}
[HttpGet]
[Route("dostuff")]
public async Task DoStuff()
{
var command = new MyCommand
{
...
};
await this.EndpointInstance.SendLocal(command);
}
}
并在global.asax
Application_Start
protected async void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
await RegisterNServiceBusWithAutofac();
}
注册NServiceBusWithAutofac
private async Task RegisterNServiceBusWithAutofac()
{
var builder = new ContainerBuilder();
var endpointConfiguration = await GetEndpointConfiguration("My.Service");
var endpointInstance = await Endpoint.Start(endpointConfiguration);
builder.RegisterInstance(endpointInstance);
var container = builder.Build();
endpointConfiguration.UseContainer<AutofacBuilder>(c => c.ExistingLifetimeScope(container));
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
}
GetEndpointConfiguration
private static async Task<EndpointConfiguration> GetEndpointConfiguration(string name)
{
var endpointConfiguration = new EndpointConfiguration(name);
// Set transport.
var routing = endpointConfiguration.UseTransport<MsmqTransport>().Routing();
// Register publish to self
routing.RegisterPublisher(typeof(EventHasFinished), name);
endpointConfiguration.UseSerialization<JsonSerializer>();
endpointConfiguration.UsePersistence<InMemoryPersistence>();
endpointConfiguration.SendFailedMessagesTo("error");
endpointConfiguration.EnableInstallers();
return endpointConfiguration;
}
结果
我在 UseContainer
行收到以下错误:
Unable to set the value for key:
NServiceBus.AutofacBuilder+LifetimeScopeHolder. The settings has been
locked for modifications. Move any configuration code earlier in the
configuration pipeline
我认为这是什么意思
我 认为 我需要在创建 endpointConfiguration
时为 NServicebus 进行所有 Autofac 注册。之后上面操作了构建器实例。
但是
我不能执行上述操作,因为我需要将 endpointinstance
注册到 IoC,因为我需要在我的控制器中发送消息。那还不存在,因为我首先需要 endpointConfiguration
。
所以我有先有鸡还是先有蛋的情况...
问题
Do I understand the issue correctly and how can I solve it while
making sure that IoC works correctly for the Controller?
即:this.EndpointInstance
已通过 IoC 正确实例化。
您可以使用 lambda 表达式注册它,而不是注册 actual 实例,该表达式将在第一次要求容器解析时执行 IEndpointInstance
.
builder
.Register(x =>
{
var endpointConfiguration = GetEndpointConfiguration("My.Service").GetAwaiter().GetResult();
var endpointInstance = Endpoint.Start(endpointConfiguration).GetAwaiter().GetResult();
return endpointInstance
})
.As<IEndpointInstance>()
.SingleInstance();
背景
我正在尝试设置需要与 NServicebus 端点通信的 Web API 2。
我需要实现 IoC,这将使用 Autofac 完成。
我有什么
控制器定义如下:
[RoutePrefix("api")]
public class Controller : ApiController
{
private IEndpointInstance EndpointInstance { get; set; }
public public MyController(IEndpointInstance endpointInstance)
{
this.EndpointInstance = endpointInstance;
}
[HttpGet]
[Route("dostuff")]
public async Task DoStuff()
{
var command = new MyCommand
{
...
};
await this.EndpointInstance.SendLocal(command);
}
}
并在global.asax
Application_Start
protected async void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
await RegisterNServiceBusWithAutofac();
}
注册NServiceBusWithAutofac
private async Task RegisterNServiceBusWithAutofac()
{
var builder = new ContainerBuilder();
var endpointConfiguration = await GetEndpointConfiguration("My.Service");
var endpointInstance = await Endpoint.Start(endpointConfiguration);
builder.RegisterInstance(endpointInstance);
var container = builder.Build();
endpointConfiguration.UseContainer<AutofacBuilder>(c => c.ExistingLifetimeScope(container));
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
}
GetEndpointConfiguration
private static async Task<EndpointConfiguration> GetEndpointConfiguration(string name)
{
var endpointConfiguration = new EndpointConfiguration(name);
// Set transport.
var routing = endpointConfiguration.UseTransport<MsmqTransport>().Routing();
// Register publish to self
routing.RegisterPublisher(typeof(EventHasFinished), name);
endpointConfiguration.UseSerialization<JsonSerializer>();
endpointConfiguration.UsePersistence<InMemoryPersistence>();
endpointConfiguration.SendFailedMessagesTo("error");
endpointConfiguration.EnableInstallers();
return endpointConfiguration;
}
结果
我在 UseContainer
行收到以下错误:
Unable to set the value for key: NServiceBus.AutofacBuilder+LifetimeScopeHolder. The settings has been locked for modifications. Move any configuration code earlier in the configuration pipeline
我认为这是什么意思
我 认为 我需要在创建 endpointConfiguration
时为 NServicebus 进行所有 Autofac 注册。之后上面操作了构建器实例。
但是
我不能执行上述操作,因为我需要将 endpointinstance
注册到 IoC,因为我需要在我的控制器中发送消息。那还不存在,因为我首先需要 endpointConfiguration
。
所以我有先有鸡还是先有蛋的情况...
问题
Do I understand the issue correctly and how can I solve it while making sure that IoC works correctly for the Controller?
即:this.EndpointInstance
已通过 IoC 正确实例化。
您可以使用 lambda 表达式注册它,而不是注册 actual 实例,该表达式将在第一次要求容器解析时执行 IEndpointInstance
.
builder
.Register(x =>
{
var endpointConfiguration = GetEndpointConfiguration("My.Service").GetAwaiter().GetResult();
var endpointInstance = Endpoint.Start(endpointConfiguration).GetAwaiter().GetResult();
return endpointInstance
})
.As<IEndpointInstance>()
.SingleInstance();