- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下 Program.cs
public class Program
{
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<ProductDbContext>();
if (context.Database.IsSqlServer())
{
context.Database.Migrate();
}
await ProductDbContextSeed.SeedSampleDataAsync(context);
}
catch (Exception ex)
{
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while migrating or seeding the database.");
throw;
}
}
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
webBuilder.UseStartup<Startup>());
}
通过添加以下行:(正如我在上面的代码中已有的):
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
我的代码按我想要的方式运行。但是,如果我删除 .UseServiceProviderFactory(new AutofacServiceProviderFactory())只需拥有:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
webBuilder.UseStartup<Startup>());
我收到以下错误:
Cannot resolve 'ProductAPI.IntegrationEvents.EventHandling.OrderCreatedIntegrationEventHandler'
from root provider because it requires scoped service
'RetailInMotion.Services.Inventory.ProductAPI.Infrastructure.Persistence.ProductDbContext'.
这是我配置 ProductDbContext 的方式:
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
{
services.AddDbContext<ProductDbContext>(options =>
options.UseSqlServer(
configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly(typeof(ProductDbContext).Assembly.FullName)));
services.AddDbContext<EventLogContext>(options =>
{
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.MigrationsAssembly(typeof(ProductDbContext).Assembly.FullName);
sqlOptions.EnableRetryOnFailure(10, TimeSpan.FromSeconds(30), null);
});
});
services.AddAuthentication();
services.AddAuthorization();
return services;
}
}
我按如下方式注册我的 EventBus:
private void RegisterEventBus(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IEventBus, EventBusRabbitMq>(sp =>
{
var subscriptionClientName = configuration["SubscriptionClientName"];
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQConnectionManagementService>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMq>>();
//var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5;
if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(configuration["EventBusRetryCount"]);
}
//return new EventBusRabbitMq(eventBusSubcriptionsManager, rabbitMQPersistentConnection, iLifetimeScope, logger, retryCount, subscriptionClientName);
return new EventBusRabbitMq(eventBusSubcriptionsManager, rabbitMQPersistentConnection, sp, logger, retryCount, subscriptionClientName);
});
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
services.AddTransient<OrderCreatedIntegrationEventHandler>();
services.AddTransient<RemoveProductStockIntegrationEventHandler>();
}
这是我的 EventBusRabbitMq 类:
`
public class EventBusRabbitMq : IEventBus, IDisposable
{
const string BROKER_NAME = "retailInMotion_event_bus";
const string AUTOFAC_SCOPE_NAME = "retailInMotion_event_bus";
private readonly IEventBusSubscriptionsManager _subsManager;
private readonly IRabbitMQConnectionManagementService _rabbitMQConnectionManagementService;
private readonly IServiceProvider _serviceProvider;
//private readonly ILifetimeScope _autofac;
private readonly ILogger<EventBusRabbitMq> _logger;
private readonly int _retryCount;
private IModel _consumerChannel;
private string _queueName;
public EventBusRabbitMq(
IEventBusSubscriptionsManager subsManager,
IRabbitMQConnectionManagementService rabbitMQConnectionManagementService,
IServiceProvider serviceProvider,
//ILifetimeScope autofac,
ILogger<EventBusRabbitMq> logger,
int retryCount = 5,
string queueName = null)
{
_subsManager = subsManager;
_rabbitMQConnectionManagementService = rabbitMQConnectionManagementService;
_serviceProvider = serviceProvider;
//_autofac = autofac;
_logger = logger;
_retryCount = retryCount;
_queueName = queueName;
_consumerChannel = CreateConsumerChannel();
_subsManager.OnEventRemoved += SubsManager_OnEventRemoved;
}
private void SubsManager_OnEventRemoved(object? sender, string eventName)
{
if (!_rabbitMQConnectionManagementService.IsConnected)
{
_rabbitMQConnectionManagementService.TryConnect();
}
using (var channel = _rabbitMQConnectionManagementService.CreateModel())
{
channel.QueueUnbind(queue: _queueName,
exchange: BROKER_NAME,
routingKey: eventName);
if (_subsManager.IsEmpty)
{
_queueName = string.Empty;
_consumerChannel.Close();
}
}
}
private IModel? CreateConsumerChannel()
{
if (!_rabbitMQConnectionManagementService.IsConnected)
{
_rabbitMQConnectionManagementService.TryConnect();
}
_logger.LogTrace("Creating RabbitMQ consumer channel");
var channel = _rabbitMQConnectionManagementService.CreateModel();
channel.ExchangeDeclare(exchange: BROKER_NAME,
type: "direct");
channel.QueueDeclare(queue: _queueName,
durable: true,
exclusive: false,
autoDelete: false,
arguments: null);
channel.CallbackException += (sender, ea) =>
{
_logger.LogWarning(ea.Exception, "Recreating RabbitMQ consumer channel");
_consumerChannel.Dispose();
_consumerChannel = CreateConsumerChannel();
StartBasicConsume();
};
return channel;
}
public void Publish(IntegrationEvent @event)
{
if (!_rabbitMQConnectionManagementService.IsConnected)
{
_rabbitMQConnectionManagementService.TryConnect();
}
var policy = RetryPolicy.Handle<BrokerUnreachableException>()
.Or<SocketException>()
.WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
{
_logger.LogWarning(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, $"{time.TotalSeconds:n1}", ex.Message);
});
var eventName = @event.GetType().Name;
//var jsonMessage = JsonConvert.SerializeObject(@event);
_logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName);
using (var channel = _rabbitMQConnectionManagementService.CreateModel())
{
_logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id);
channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct");
var body = JsonSerializer.SerializeToUtf8Bytes(@event, @event.GetType(), new JsonSerializerOptions
{
WriteIndented = true
});
//var body = Encoding.UTF8.GetBytes(jsonMessage);
policy.Execute(() =>
{
var properties = channel.CreateBasicProperties();
properties.DeliveryMode = 2; // persistent
_logger.LogTrace("Publishing event to RabbitMQ: {EventId}", @event.Id);
channel.BasicPublish(
exchange: BROKER_NAME,
routingKey: eventName,
mandatory: true,
basicProperties: properties,
body: body);
});
}
}
//public void Setup()
//{
// throw new NotImplementedException();
//}
public void Subscribe<T, TH>()
where T : IntegrationEvent
where TH : IIntegrationEventHandler<T>
{
var eventName = _subsManager.GetEventKey<T>();
DoInternalSubscription(eventName);
_logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).Name);
_subsManager.AddSubscription<T, TH>();
StartBasicConsume();
}
private void DoInternalSubscription(string eventName)
{
var containsKey = _subsManager.HasSubscriptionsForEvent(eventName);
if (!containsKey)
{
if (!_rabbitMQConnectionManagementService.IsConnected)
{
_rabbitMQConnectionManagementService.TryConnect();
}
_consumerChannel.QueueBind(queue: _queueName,
exchange: BROKER_NAME,
routingKey: eventName);
}
}
public void Unsubscribe<T, TH>()
where T : IntegrationEvent
where TH : IIntegrationEventHandler<T>
{
var eventName = _subsManager.GetEventKey<T>();
_logger.LogInformation("Unsubscribing from event {EventName}", eventName);
_subsManager.RemoveSubscription<T, TH>();
}
private void StartBasicConsume()
{
_logger.LogTrace("Starting RabbitMQ basic consume");
if (_consumerChannel != null)
{
var consumer = new AsyncEventingBasicConsumer(_consumerChannel);
consumer.Received += Consumer_Received;
_consumerChannel.BasicConsume(
queue: _queueName,
autoAck: false,
consumer: consumer);
}
else
{
_logger.LogError("StartBasicConsume can't call on _consumerChannel == null");
}
}
private async Task Consumer_Received(object sender, BasicDeliverEventArgs eventArgs)
{
var eventName = eventArgs.RoutingKey;
var message = Encoding.UTF8.GetString(eventArgs.Body.Span);
try
{
if (message.ToLowerInvariant().Contains("throw-fake-exception"))
{
throw new InvalidOperationException($"Fake exception requested: \"{message}\"");
}
await ProcessEvent(eventName, message);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "----- ERROR Processing message \"{Message}\"", message);
}
// Even on exception we take the message off the queue.
// in a REAL WORLD app this should be handled with a Dead Letter Exchange (DLX).
// For more information see: https://www.rabbitmq.com/dlx.html
_consumerChannel.BasicAck(eventArgs.DeliveryTag, multiple: false);
}
private async Task ProcessEvent(string eventName, string message)
{
_logger.LogTrace("Processing RabbitMQ event: {EventName}", eventName);
if (_subsManager.HasSubscriptionsForEvent(eventName))
{
//using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME)) // can do it this way with autofac or like directly below with built in .net core DI
using (var scope = _serviceProvider.CreateScope())
{
var subscriptions = _subsManager.GetHandlersForEvent(eventName);
foreach (var subscription in subscriptions)
{
var handler = _serviceProvider.GetRequiredService(subscription.HandlerType); //CHRIS INVESTIGATE!!
//var handler = scope.ResolveOptional(subscription.HandlerType);
if (handler == null) continue;
var eventType = _subsManager.GetEventTypeByName(eventName);
//var integrationEvent = JsonConvert.DeserializeObject(message, eventType);
//dynamic json = Newtonsoft.Json.JsonConvert.DeserializeObject(message);
//using dynamic eventData = JsonDocument.Parse(message);
var integrationEvent = JsonSerializer.Deserialize(message, eventType, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true}); //JsonSerializer.Deserialize(message, eventType, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType);
await (Task)concreteType.GetMethod("HandleAsync").Invoke(handler, new object[] { integrationEvent });
}
}
}
else
{
_logger.LogWarning("No subscription for RabbitMQ event: {EventName}", eventName);
}
}
public void Dispose()
{
if (_consumerChannel != null)
{
_consumerChannel.Dispose();
}
_subsManager.Clear();
}
}`
这是我收到的错误的堆栈跟踪:
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(Type serviceType, IServiceScope scope, IServiceScope rootScope) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at EventBus.EventBusRabbitMq.<ProcessEvent>d__18.MoveNext() in C:\Users\porterc\Documents\My Version of DDD\RetailInMotion-master\EventBus\EventBusRabbitMq.cs:line 260 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at EventBus.EventBusRabbitMq.<Consumer_Received>d__17.MoveNext() in C:\Users\porterc\Documents\My Version of DDD\RetailInMotion-master\EventBus\EventBusRabbitMq.cs:line 235
我的问题是为什么?如果有人能指出我正确的方向或告诉我这一行实际上做了什么,我将不胜感激。
最佳答案
如异常消息所述,您的 ProductAPI.IntegrationEvents.EventHandling.OrderCreatedIntegrationEventHandler
未在范围内解析或未注册为范围服务。
无论您使用什么事件调度程序,都应该在解析事件处理程序和处理事件之前开始一个范围。并且 OrderCreatedIntegrationEventHandler
也必须注册为范围内的服务。
我的猜测是 Autofac 在启动时不会执行任何生命周期不匹配检查,这就是为什么当您插入 Autofac 时它不会抛出异常。这并不意味着它确实有效,只是你隐藏了一个潜在的错误。它可能在您第一次处理事件时作为异常出现,或者它可能更严重,因为它在事件处理程序的生命周期内使用相同的 ProductDbContext,这可能是单例。
但请注意,我没有使用过 Autofac,只使用过其他容器,所以我不知道这个库究竟是如何处理此类问题的。
编辑 1
此行 (260):var handler = _serviceProvider.GetRequiredService(subscription.HandlerType);
在为 EventBusRabbitMq 提供的源中需要更改为:var handler = scope.ServiceProvicer。 GetRequiredService(subscription.HandlerType);
.
在范围内,您应该使用范围解析您的服务(而不是从您创建范围的根服务提供商 _serviceProvider
)。
关于c# - 无法从根提供程序解析,因为它需要范围内的服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72635535/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!