提问人:Sagar Tube 提问时间:9/3/2023 更新时间:9/3/2023 访问量:35
自定义 DataAnnotation 和依赖关系注入
Custom DataAnnotation and Dependency Injection
问:
我有 2 个模型类 Batch 和 Coach,如下所示
批处理 .cs
public class Batch
{
public int Id { get; set; }
public string Name { get; set; }
[NoBatchAfter9PM]
public TimeSpan StartTime { get; set; }
[NoBatchAfter9PM]
public TimeSpan EndTime { get; set; }
public string? Description { get; set; }
[Display(Name="Is it a Weekend batch?")]
public bool IsWeekendBatch { get; set; }
[Display(Name = "Is it a Womens batch?")]
public bool IsWomenBatch { get; set; }
public ICollection<Learner>? Learners { get; set; }
public Coach? Coach { get; set; }
}
教练 .cs
public class Coach
{
public int Id { get; set; }
public string Name { get; set; }
[Display(Name="Gender")]
public GenderId GenderId { get; set; }
[Display(Name = "Batch")]
public int BatchId { get; set; }
[ForeignKey("BatchId")]
public Batch Batch { get; set; }
[ForeignKey("GenderId")]
public Gender Gender { get; set; }
}
他们都有一对多的关系。
在 CoachForm 中,我有一个批处理字段的下拉列表。提交表单时 我必须检查教练的性别,如果性别是女性,而批次是女性批次,那么只有 ModelValidation 才能成功,我为此创建了一个自定义 DataAnnotation,如下所示。
public class CheckForGenderAndBatch:ValidationAttribute
{
IBatchRepository batchRepository;
static List<Batch> WomensBatch;
public CheckForGenderAndBatch(IBatchRepository batchRepository)
{
this.batchRepository = batchRepository;
WomensBatch = batchRepository.GetBatches().Where(x => x.IsWomenBatch).ToList();
}
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
Coach coach = (Coach)validationContext.ObjectInstance;
if (coach.GenderId == GenderId.Male && WomensBatch.Any(x => x.Id == coach.BatchId))
{
return new ValidationResult("Only Female Coach is allowed in womens batch");
}
return ValidationResult.Success;
}
}
对于 IBatchRepository 接口,我已经注册了一个具体类,如下所示 Program.cs
builder.Services.AddTransient<IBatchRepository, BatchProjectDbRepository>();
当我在 Coach.cs 中的属性 BatchId 顶部添加属性时,如下所示,我收到以下错误。
我知道自定义数据注释中没有默认构造函数,因此我尝试传递 Repository 类的引用,如下所示。
[CheckForGenderAndBatch(new BatchProjectDbRepository())]
[Display(Name = "Batch")]
public int BatchId { get; set; }
但这里的问题是,即使是 BatchProjectDbRepository 类也没有默认构造函数。BatchProjectDbRepository 类的结构如下所示。
ProjectDbContext context;
public BatchProjectDbRepository(ProjectDbContext context)
{
this.context = context;
}
因此,考虑将 ProjectDbContext 对象传递给它,如下所示。
[CheckForGenderAndBatch(new BatchProjectDbRepository(new ProjectDbContext()))]
[Display(Name = "Batch")]
public int BatchId { get; set; }
但是由于 ProjectDbContext 类构造函数也需要一个参数,因此我收到以下错误
所以我的问题是,无论如何,我们是否可以将具体类的对象注入到自定义数据注释的类中?
(很抱歉以如此冗长的方式定义问题)
答:
我明白你想做什么。 无需使用构造函数注入服务。
您必须在运行时使用对象和方法获取实现ValidationContext
GetService
-步骤
1-使你的验证器类的承包商无参数。CheckForGenderAndBatch
2-内使用这条线IsValid
var batchRepository = (IBatchRepository ) validationContext.GetService(typeof(IBatchRepository ));
现在,可以通过对象来使用存储库。batchRepository
还有一件事:始终将您的存储库声明为 DI 容器内的范围。
旁注在这种情况下,构造函数用于获取与验证域相关的更多数据,例如,假设您正在尝试验证余额阈值,然后在构造函数中发送所需的阈值值,使验证器尽可能可用。
另一个示例是在构造函数中发送的长度验证,即字符串应超过的长度值,例如 150 个字符。
祝你好运
评论