我看到了使用Asp.Net Core 3.1和Mediatr(使用IPipelineBehavior)的以下代码。
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPerformanceBehaviour<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>));
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FluentValidation;
using MediatR;
using ValidationException = CleanArchitecture.Application.Common.Exceptions.ValidationException;
public class RequestValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public RequestValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
if (_validators.Any())
{
var context = new ValidationContext(request);
var failures = _validators
.Select(v => v.Validate(context))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Count != 0)
{
throw new ValidationException(failures);
}
}
return next();
}
}
但是,基于我对asp.net DI的有限了解,_validators
的类型应该不是IValidator<TRequest>
吗?为什么类型为IEnumerable<IValidator<TRequest>>
?
运行代码时,_validators
的长度始终为1。
在哪里可以找到有关DI将何时将实现解析为IEnumerable的更多文档?
感谢Deepak Mishra和Steven帮助我理解。我了解到,这就是dotnet DI解决同一接口的多种实现的方式。要获得所有实现,我将使用IEnumerable<Interface>
获取实现它的所有服务。这是一个演示此操作的示例:
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
namespace DotnetCoreDependencyInjection
{
class Program
{
static void Main(string[] args)
{
IServiceCollection services = new ServiceCollection();
services.AddSingleton<IValidator<Shipment>, ValidateSourceAddress>();
services.AddSingleton<IValidator<Shipment>, ValidateDestinationAddress>();
var serviceProvider = services.BuildServiceProvider();
using var scope = serviceProvider.CreateScope();
// DI will resolve IEnumerable<IValidator<Shipment>> to all implementations of IValidator<Shipment>
var validators = scope.ServiceProvider.GetService<IEnumerable<IValidator<Shipment>>>();
foreach (var validator in validators)
{
validator.Validate(new Shipment{ SourceAddress = "Source Address", DestinationAddress = "Destination Address"});
}
}
}
class Shipment
{
public int Id { get; set; }
public string DestinationAddress { get; set; }
public string SourceAddress { get; set; }
}
interface IValidator<T>
{
void Validate(T shipment);
}
class ValidateSourceAddress : IValidator<Shipment>
{
public void Validate(Shipment shipment)
{
Console.WriteLine($"Validate SourceAddress: {shipment.SourceAddress}");
}
}
class ValidateDestinationAddress : IValidator<Shipment>
{
public void Validate(Shipment shipment)
{
Console.WriteLine($"Validate DestinationAddress: {shipment.DestinationAddress}");
}
}
}
答案 0 :(得分:1)
注册同一接口的多个实现时,DI可以使用包含所有实现的IEnumerable进行解析。如果未指定IEnumerable,则它将仅包含第一个实现。