У меня есть общий список c объектов, но все типы в списке разные. Однако при выполнении итерации по списку объектов и последующем вызове функции generi c тип T, определенный в generi c, имеет тип Object. Как я могу заставить сопоставление с образцом работать так, чтобы тип T соответствовал конкретному типу проверяемого объекта? Например, в нижеприведенном надуманном примере при вызове Validate для ValidationService строка
if(validator is IValidator<T> typedValidator)
всегда завершается ошибкой, поскольку тип T является объектом, а физическая реализация будет IValidator<Widget>
или IValidator<Entity>
. Как мне изменить метод DemonstrateProblem()
, чтобы при вызове validationService.Validate
использовался конкретный тип функции, а не тип типа, определенный в List<object>
? Чтобы сделать его немного сложнее, мой реальный код также асинхронный, поэтому мне нужно возвращаемое значение Task<IValidationResult<T>>
namespace Contrived
{
public interface IValidator { }
public interface IValidationResult<T> { }
public interface IValidator<T> : IValidator
{
IValidationResult<T> Validate(T entity);
}
public class ValidationResult<T> : IValidationResult<T>
{
public bool IsValid { get; set; }
}
public class Entity
{
public int Id { get; set; }
public string SomeProperty { get; set; }
}
public class EntityValidator : Contrived.IValidator<Entity>
{
public IValidationResult<Entity> Validate(Entity entity)
{
return new ValidationResult<Entity>() { IsValid = true };
}
}
public class Widget
{
public Guid UniqueIdentifier { get; set; }
}
public class WidgetValidator : IValidator<Widget>
{
public IValidationResult<Widget> Validate(Widget entity)
{
return new ValidationResult<Widget>() { IsValid = true };
}
}
public class ValidationService
{
private readonly Dictionary<Type, IValidator> validators;
public ValidationService(Dictionary<Type, IValidator> validators)
{
this.validators = validators;
}
public IValidationResult<T> Validate<T>(T validatingObject)
{
var validator = validators[validatingObject.GetType()];
if (validator is IValidator<T> typedValidator)
{
return typedValidator.Validate(validatingObject);
}
else throw new UnknownValidationType($"No known validator for type of {validatingObject.GetType()}");
}
}
public class ServiceUser
{
private readonly ValidationService validationService;
public ServiceUser(ValidationService validationService)
{
this.validationService = validationService;
}
public void DemonstrateProblem()
{
Widget widget = new Widget() { UniqueIdentifier = Guid.NewGuid() };
Entity entity = new Entity() { Id = 1, SomeProperty = "You know" };
List<object> ObjectsToBeValidated = new List<object>() { widget, entity };
foreach(var t in ObjectsToBeValidated)
{
validationService.Validate(t);//The Generic type of T is Object because that is the type of the List.
//How to get to be the concrete type of Widget and Entity?
}
}
}
public class UnknownValidationType : Exception {
public UnknownValidationType(string message) : base(message)
{
}
}
}