Questa domanda ha una certa sovrapposizione abbastanza pesante con questi:
Ti consigliamo di controllare quelli fuoriper alcune idee
La risposta breve è: questo genere di cose non è supportato immediatamente. Avrai bisogno di fare un paio di cose.
Opzione: è possibile avere un contenitore diverso per i thread in background. Ciò non consentirebbe di condividere i singleton a livello di applicazione, ma potrebbe essere corretto per l'applicazione.
Opzione: è possibile creare due ambiti di durata del contenitore e fare le diverse registrazioni come parte della chiamata a BeginLifetimeScope
. Ciò consentirebbe di condividere i singleton a livello di applicazione e avere ambiti di vita diversi per gli stessi componenti in diversi contesti. Tuttavia, è un po 'più difficile gestire le registrazioni, e avrete bisogno di due diversi localizzatori di servizio (ad es., DependencyResolver
) perché ogni contesto logico dovrebbe risolversi dal proprio ambito.
var builder = new ContainerBuilder();
builder.RegisterType<AppLevelSingleton>().SingleInstance();
var container = builder.Build();
// Create a nested lifetime scope for your background threads
// that registers things as InstancePerDependency, etc. Pass
// that scope to whatever handles dependency resolution on the thread.
var backgroundScope = container.BeginLifetimeScope(
b => b.RegisterType<DatabaseFactory>()
.As<IDatabaseFactory>()
.InstancePerDependency());
// Create a nested lifetime scope for the web app that registers
// things as InstancePerHttpRequest, etc. Pass that scope
// as the basis for the MVC dependency resolver.
var webScope = container.BeginLifetimeScope(
b => b.RegisterType<DatabaseFactory>()
.As<IDatabaseFactory>()
.InstancePerHttpRequest());
var resolver = new AutofacDependencyResolver(webScope);
DependencyResolver.SetResolver(resolver);
Se davvero si voleva ottenere l'immaginazione con questa opzione, è possibile implementare una consuetudine IContainer
in grado di rilevare quale contesto è dentro e risolve le cose dal campo di applicazione nidificato appropriata. Questo è il modo in cui il supporto di Autofac multi-tenant funziona. Tuttavia, questa è una soluzione molto più coinvolgente, quindi non scriverò tutto qui. Controllare la sorgente di Autofac per il supporto del multitenant per gli esempi.
Opzione: Si potrebbe utilizzare una sorta "comune minimo denominatore" di registrazione come InstancePerDependency
o InstancePerLifetimeScope
e saltare l'idea di avere una vita diversa per le diverse parti dell'applicazione.
Si noti che, in questo momento, tecnicamente, internamente, non v'è alcuna differenza tra ciò che InstancePerHttpRequest
e InstancePerWebApiRequest
fare. Entrambi si riducono esattamente alla stessa cosa e sono effettivamente intercambiabili. (Non posso promettere che sarà sempre così per sempre, ma non so perché dovrebbe cambiare.)
Fantastico! Grazie per la risposta approfondita, questo aiuta molto. – chriskopec
pensa che sarebbe utile. un esempio utilizza l'infrastruttura EF dall'azione dbcontext web api, se chiama la classe che ha bisogno di accedere al database con un nuovo thread, è probabile che sia solo instanceperhttprequest, genererà un'eccezione, quindi è necessario avere la flessibilità per avere InstancePerLifetimeScope. è quasi meglio avere solo InstancePerLifetimeScope. – koo9