Sto tentando di utilizzare Autofac per iniettare dipendenze in FluentValidation in un'app MVC 4. Penso di aver risolto la strategia, ma mi sto bloccando con la risoluzione della mia richiesta ISomething da un singleton.Autofac - come risolvere Func per ISomething da Singleton dove ISomething è InstancePerHttpRequest
Ecco lo scenario: Ho un validatore che deriva da AbstractValidator di FluentValidation. Ho letto che i validatori di FluentValidation funzionano al meglio come singleton, quindi il mio costruttore si aspetta un Func e lo memorizza per essere utilizzato in seguito. Quando viene utilizzato il validatore, dovrebbe chiedere al factory archiviato un IDataStore, ottenere l'istanza creata per quella richiesta e utilizzarla. Questa è la teoria. Voglio dare credito allo https://github.com/robdmoore/UnobtrusiveMVCTechniques, che mi ha aiutato a risolvere questa soluzione. Ecco il validatore ...
public class SiteAdminViewModelValidator : AbstractValidator<SiteAdminViewModel> {
private readonly Func<IDataStore> _dbFactory;
public SiteAdminViewModelValidator(Func<IDataStore> dbFactory) {
_dbFactory = dbFactory;
RuleFor(model => model.SiteCode).Length(1, 40).Must(BeSpecial);
}
public bool BeSpecial(string siteCode) {
var db = _dbFactory();
List<Stuff> stuffs = db.All<Stuff>().ToList();
return true;
}
}
Se qualcuno mi può indicare un esempio funzionante di quello che sto cercando di realizzare, che sarebbe grande, ma mi piacerebbe anche sapere la soluzione a questo particolare pezzo di trucidosità di Autofac.
Ecco la mia registrazione del validatore ...
public class FluentValidatorModule : Module {
protected override void Load(ContainerBuilder builder) {
base.Load(builder);
builder.RegisterType<AutofacValidatorFactory>().As<IValidatorFactory>().SingleInstance();
var validators = AssemblyScanner.FindValidatorsInAssembly(System.Reflection.Assembly.GetExecutingAssembly());
validators.ToList().ForEach(v => builder.RegisterType(v.ValidatorType).As(v.InterfaceType).SingleInstance());
}
}
Ecco la mia registrazione per la fabbrica IDataStore ...
builder.RegisterType<SuperDB>().As<IDataStore>().InstancePerHttpRequest();
builder.Register<Func<IDataStore>>(c => {
var context = c.Resolve<IComponentContext>();
return context.Resolve<IDataStore>;
});
Ecco l'errore che sto ottenendo quando il mio validatore richiede un IDataStore su la riga - var db = _dbFactory();
Nessun ambito con un tag corrispondente a "AutofacWebRequest" è visibile dall'ambito in cui è stata richiesta l'istanza. Questo indica generalmente che un componente registrato come per-HTTP richiesta sta per essere richiesto da un SingleInstance() componente (o di uno scenario simile.) Sotto l'integrazione web richiedere sempre le dipendenze dal DependencyResolver.Current o ILifetimeScopeProvider.RequestLifetime, mai dal contenitore stesso.
... che è esattamente quello che ho ottenuto quando ho provato prima di scrivere la mia propria registrazione di fabbrica - la registrazione di Func. Dalla lettura di varie risposte a domande simili, sembrava che quello che ho sopra dovrebbe funzionare perché pensavo che ora stavo risolvendo il Func per ottenere il risolutore corrente.
Qualsiasi aiuto sarà molto apprezzato.
Questo funziona! Grazie. Sono nuovo di Autofac. Posso ottenere solo un breve chiarimento sulla registrazione del builder.RegisterInstance (PerHttpSafeResolve [IDataStore]()); linea? Così dice "ogni volta che qualcuno chiede un Func [IDataStore], usa questo metodo per dargliene uno"? –
Vedi la mia modifica - cercherò di spiegarlo – Felix
Bello !! Quella tecnica è incredibile. Lo adoro. Tanto che ho scritto un post sul blog: http://robdmoore.id.au/blog/2013/03/23/resolving-request-scoped-objects-into-a-singleton-with-autofac/. Se hai un blog tu stesso fammelo sapere e ci collegherò ad esso invece del tuo SO user. –