TL; DR: Comment consolider la logique partagée par deux implémentations ModelBinder
personnalisées dans une seule classe de base, lorsque les deux implémentations s'appuient sur Autofac pour leur injecter une dépendance (commune)? ?Injection d'un service dans une classe de base avec Autofac
Lors de l'examen du code dans un projet ASP.NET MVC je travaille, je réalisais que j'ai deux classeurs de modèles personnalisés qui font essentiellement ils même chose. Ils héritent tous les deux de DefaultModelBinder
, et ils codent tous les deux une seule propriété sur deux classes de modèles de vues distinctes, en utilisant un IEncodingService
qui est injecté dans leurs constructeurs.
public class ResetQuestionAndAnswerViewModelBinder : DefaultModelBinder {
public ResetQuestionAndAnswerViewModelBinder(IEncodingService encodingService) {
encoder = encodingService;
}
private readonly IEncodingService encoder;
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
var model = base.BindModel(controllerContext, bindingContext) as ResetQuestionAndAnswerViewModel;
if (model != null) {
var answer = bindingContext.ValueProvider.GetValue("Answer");
if ((answer != null) && !(answer.AttemptedValue.IsNullOrEmpty())) {
model.Answer = encoder.Encode(answer.AttemptedValue);
}
}
return model;
}
}
public class ConfirmIdentityViewModelBinder : DefaultModelBinder {
public ConfirmIdentityViewModelBinder(IEncodingService encodingService) {
encoder = encodingService;
}
private readonly IEncodingService encoder;
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
var model = base.BindModel(controllerContext, bindingContext) as ConfirmIdentityViewModel;
if (model != null) {
var secretKey = bindingContext.ValueProvider.GetValue("SecretKey");
if ((secretKey != null) && !(secretKey.AttemptedValue.IsNullOrEmpty())) {
model.SecretKeyHash = encoder.Encode(secretKey.AttemptedValue);
}
}
return model;
}
}
j'ai écrit une classe de base générique pour ces deux classes pour hériter de:
public class EncodedPropertyModelBinder<TViewModel> : DefaultModelBinder
where TViewModel : class {
public EncodedPropertyModelBinder(IEncodingService encodingService,
string propertyName) {
encoder = encodingService;
property = propertyName;
}
private readonly IEncodingService encoder;
private readonly string property;
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
var model = base.BindModel(controllerContext, bindingContext) as TViewModel;
if (model != null) {
var value = bindingContext.ValueProvider.GetValue(property);
if ((value != null) && !(value.AttemptedValue.IsNullOrEmpty())) {
var encodedValue = encoder.Encode(value.AttemptedValue);
var propertyInfo = model.GetType().GetProperty(property);
propertyInfo.SetValue(model, encodedValue, null);
}
}
return model;
}
}
En utilisant Autofac, comment pourrais-je injecter le IEncodingService
dans le constructeur de la classe de base, tout en forçant les classes dérivées à fournir le nom de la propriété à encoder?