mirror of
https://github.com/meysamhadeli/booking-microservices.git
synced 2026-04-28 08:50:23 +08:00
- Fix problem load assemblies in test cli
- Add Test pipeline to ci-cd
This commit is contained in:
parent
6a410a7b05
commit
97ab953975
2
.github/workflows/dotnet.yml
vendored
2
.github/workflows/dotnet.yml
vendored
@ -21,4 +21,6 @@ jobs:
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
run: dotnet build -c Release --no-restore
|
||||
- name: Test
|
||||
run: dotnet test -c Release --no-restore
|
||||
|
||||
|
||||
@ -18,8 +18,8 @@ public static class Extensions
|
||||
bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER"), out var inContainer) &&
|
||||
inContainer;
|
||||
|
||||
public static IServiceCollection AddCustomMassTransit(this IServiceCollection services, Assembly assembly,
|
||||
IWebHostEnvironment env)
|
||||
public static IServiceCollection AddCustomMassTransit(this IServiceCollection services,
|
||||
IWebHostEnvironment env, Assembly assembly)
|
||||
{
|
||||
services.AddOptions<RabbitMqOptions>()
|
||||
.BindConfiguration(nameof(RabbitMqOptions))
|
||||
@ -29,22 +29,22 @@ public static class Extensions
|
||||
{
|
||||
services.AddMassTransitTestHarness(configure =>
|
||||
{
|
||||
SetupMasstransitConfigurations(services, assembly, configure);
|
||||
SetupMasstransitConfigurations(services, configure, assembly);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddMassTransit(configure =>
|
||||
{
|
||||
SetupMasstransitConfigurations(services, assembly, configure);
|
||||
SetupMasstransitConfigurations(services, configure, assembly);
|
||||
});
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
private static void SetupMasstransitConfigurations(IServiceCollection services, Assembly assembly,
|
||||
IBusRegistrationConfigurator configure)
|
||||
private static void SetupMasstransitConfigurations(IServiceCollection services,
|
||||
IBusRegistrationConfigurator configure, Assembly assembly)
|
||||
{
|
||||
configure.AddConsumers(assembly);
|
||||
|
||||
@ -60,38 +60,44 @@ public static class Extensions
|
||||
h.Password(rabbitMqOptions?.Password);
|
||||
});
|
||||
|
||||
var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
|
||||
|
||||
var integrationEventRootAssemblies = Assembly.GetAssembly(typeof(IIntegrationEvent));
|
||||
|
||||
var types = integrationEventRootAssemblies?.GetTypes()
|
||||
.Where(x => x.IsAssignableTo(typeof(IIntegrationEvent))
|
||||
&& !x.IsInterface
|
||||
&& !x.IsAbstract
|
||||
&& !x.IsGenericType);
|
||||
&& !x.IsGenericType)?.ToList();
|
||||
|
||||
foreach (var type in types)
|
||||
if (types != null && types.Any())
|
||||
{
|
||||
var consumers = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
|
||||
.Where(x => x.IsAssignableTo(typeof(IConsumer<>).MakeGenericType(type))).ToList();
|
||||
foreach (var type in types)
|
||||
{
|
||||
var consumers = assembly?.GetTypes()
|
||||
.Where(x => x.IsAssignableTo(typeof(IConsumer<>).MakeGenericType(type))).ToList();
|
||||
|
||||
if (consumers.Any())
|
||||
configurator.ReceiveEndpoint(
|
||||
string.IsNullOrEmpty(rabbitMqOptions.ExchangeName)
|
||||
? type.Name.Underscore()
|
||||
: $"{rabbitMqOptions.ExchangeName}_{type.Name.Underscore()}", e =>
|
||||
{
|
||||
e.UseConsumeFilter(typeof(ConsumeFilter<>), context); //generic filter
|
||||
|
||||
foreach (var consumer in consumers)
|
||||
if (consumers != null && consumers.Any())
|
||||
configurator.ReceiveEndpoint(
|
||||
string.IsNullOrEmpty(rabbitMqOptions.ExchangeName)
|
||||
? type.Name.Underscore()
|
||||
: $"{rabbitMqOptions.ExchangeName}_{type.Name.Underscore()}", e =>
|
||||
{
|
||||
configurator.ConfigureEndpoints(context, x => x.Exclude(consumer));
|
||||
var methodInfo = typeof(DependencyInjectionReceiveEndpointExtensions)
|
||||
.GetMethods()
|
||||
.Where(x => x.GetParameters()
|
||||
.Any(p => p.ParameterType == typeof(IServiceProvider)))
|
||||
.FirstOrDefault(x => x.Name == "Consumer" && x.IsGenericMethod);
|
||||
e.UseConsumeFilter(typeof(ConsumeFilter<>), context); //generic filter
|
||||
|
||||
var generic = methodInfo?.MakeGenericMethod(consumer);
|
||||
generic?.Invoke(e, new object[] {e, context, null});
|
||||
}
|
||||
});
|
||||
foreach (var consumer in consumers)
|
||||
{
|
||||
configurator.ConfigureEndpoints(context, x => x.Exclude(consumer));
|
||||
var methodInfo = typeof(DependencyInjectionReceiveEndpointExtensions)
|
||||
.GetMethods()
|
||||
.Where(x => x.GetParameters()
|
||||
.Any(p => p.ParameterType == typeof(IServiceProvider)))
|
||||
.FirstOrDefault(x => x.Name == "Consumer" && x.IsGenericMethod);
|
||||
|
||||
var generic = methodInfo?.MakeGenericMethod(consumer);
|
||||
generic?.Invoke(e, new object[] { e, context, null });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||
|
||||
namespace BuildingBlocks.Utils;
|
||||
|
||||
@ -36,4 +37,49 @@ public static class TypeProvider
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IReadOnlyList<Assembly> GetReferencedAssemblies(Assembly? rootAssembly)
|
||||
{
|
||||
var visited = new HashSet<string>();
|
||||
var queue = new Queue<Assembly?>();
|
||||
var listResult = new List<Assembly>();
|
||||
|
||||
var root = rootAssembly ?? Assembly.GetEntryAssembly();
|
||||
queue.Enqueue(root);
|
||||
|
||||
do
|
||||
{
|
||||
var asm = queue.Dequeue();
|
||||
|
||||
if (asm == null)
|
||||
break;
|
||||
|
||||
listResult.Add(asm);
|
||||
|
||||
foreach (var reference in asm.GetReferencedAssemblies())
|
||||
{
|
||||
if (!visited.Contains(reference.FullName))
|
||||
{
|
||||
// Load will add assembly into the application domain of the caller. loading assemblies explicitly to AppDomain, because assemblies are loaded lazily
|
||||
// https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.load
|
||||
queue.Enqueue(Assembly.Load(reference));
|
||||
visited.Add(reference.FullName);
|
||||
}
|
||||
}
|
||||
} while (queue.Count > 0);
|
||||
|
||||
return listResult.Distinct().ToList().AsReadOnly();
|
||||
}
|
||||
|
||||
public static IReadOnlyList<Assembly> GetApplicationPartAssemblies(Assembly rootAssembly)
|
||||
{
|
||||
var rootNamespace = rootAssembly.GetName().Name!.Split('.').First();
|
||||
var list = rootAssembly!.GetCustomAttributes<ApplicationPartAttribute>()
|
||||
.Where(x => x.AssemblyName.StartsWith(rootNamespace, StringComparison.InvariantCulture))
|
||||
.Select(name => Assembly.Load(name.AssemblyName))
|
||||
.Distinct();
|
||||
|
||||
return list.ToList().AsReadOnly();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using System.Reflection;
|
||||
using BuildingBlocks.Utils;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Scrutor;
|
||||
@ -10,10 +12,19 @@ public static class MinimalApiExtensions
|
||||
|
||||
public static IServiceCollection AddMinimalEndpoints(
|
||||
this WebApplicationBuilder applicationBuilder,
|
||||
ServiceLifetime lifetime = ServiceLifetime.Scoped)
|
||||
ServiceLifetime lifetime = ServiceLifetime.Scoped,
|
||||
params Assembly[] assemblies)
|
||||
{
|
||||
|
||||
var scanAssemblies = assemblies.Any()
|
||||
? assemblies
|
||||
: TypeProvider.GetReferencedAssemblies(Assembly.GetCallingAssembly())
|
||||
.Concat(TypeProvider.GetApplicationPartAssemblies(Assembly.GetCallingAssembly()))
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
|
||||
applicationBuilder.Services.Scan(scan => scan
|
||||
.FromAssemblies(AppDomain.CurrentDomain.GetAssemblies())
|
||||
.FromAssemblies(scanAssemblies)
|
||||
.AddClasses(classes => classes.AssignableTo(typeof(IMinimalEndpoint)))
|
||||
.UsingRegistrationStrategy(RegistrationStrategy.Append)
|
||||
.As<IMinimalEndpoint>()
|
||||
|
||||
@ -72,7 +72,7 @@ public static class InfrastructureExtensions
|
||||
builder.Services.AddCustomProblemDetails();
|
||||
builder.Services.AddCustomMapster(typeof(BookingRoot).Assembly);
|
||||
builder.Services.AddCustomHealthCheck();
|
||||
builder.Services.AddCustomMassTransit(typeof(BookingRoot).Assembly, env);
|
||||
builder.Services.AddCustomMassTransit(env, typeof(BookingRoot).Assembly);
|
||||
builder.Services.AddCustomOpenTelemetry();
|
||||
builder.Services.AddTransient<AuthHeaderHandler>();
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ public static class InfrastructureExtensions
|
||||
builder.Services.AddValidatorsFromAssembly(typeof(FlightRoot).Assembly);
|
||||
builder.Services.AddCustomMapster(typeof(FlightRoot).Assembly);
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
builder.Services.AddCustomMassTransit(typeof(FlightRoot).Assembly, env);
|
||||
builder.Services.AddCustomMassTransit(env, typeof(FlightRoot).Assembly);
|
||||
builder.Services.AddCustomOpenTelemetry();
|
||||
builder.Services.AddCustomHealthCheck();
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ public static class InfrastructureExtensions
|
||||
builder.Services.AddCustomMapster(typeof(IdentityRoot).Assembly);
|
||||
builder.Services.AddCustomHealthCheck();
|
||||
|
||||
builder.Services.AddCustomMassTransit(typeof(IdentityRoot).Assembly, env);
|
||||
builder.Services.AddCustomMassTransit(env, typeof(IdentityRoot).Assembly);
|
||||
builder.Services.AddCustomOpenTelemetry();
|
||||
|
||||
SnowFlakIdGenerator.Configure(4);
|
||||
|
||||
@ -73,7 +73,7 @@ public static class InfrastructureExtensions
|
||||
builder.Services.AddCustomMapster(typeof(PassengerRoot).Assembly);
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
builder.Services.AddCustomHealthCheck();
|
||||
builder.Services.AddCustomMassTransit(typeof(PassengerRoot).Assembly, env);
|
||||
builder.Services.AddCustomMassTransit(env, typeof(PassengerRoot).Assembly);
|
||||
builder.Services.AddCustomOpenTelemetry();
|
||||
builder.Services.AddGrpc(options =>
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user