我正在开发一个 ASP.NET(不是 Core,而是基于 .NET Framework)WebAPI 项目。它使用 Autofac 进行 DI。我需要通过 Autofac 实现 Singleton/SingleInstance。但该类会针对每个 API 请求进行实例化。我想要的是一个在应用程序的整个运行时都存在并且始终相同的对象。独立于任何 API 请求。 控制器在构造函数中请求对象,Autofac 正确地传递该对象的一个实例,但它始终是一个新实例。 唯一的例外是,当我使用 AutoActivate 启动 SingleInstance 时,它被创建了,然后第一个请求获得了相同的实例,但随后的每个请求都收到了一个新实例。 我使用当前的 Autofac 版本 7.x 和 OWIN。 相关班级名为
ScriptExecutionHost
。它仅请求一个字符串作为参数和另外两个单例。详情请参阅下文。
相关代码如下: Startup.cs 摘录
public void Configuration(IAppBuilder app)
{
// See the code for this method blow
var container = ContainerConfig.Configure();
app.UseAutofacMiddleware(container);
app.UseAutofacLifetimeScopeInjector(container);
app.UseCors(CorsOptions.AllowAll);
ConfigureOAuth(app);
var config = new HttpConfiguration { DependencyResolver = new AutofacWebApiDependencyResolver(container) };
WebApiConfig.Register(config);
app.UseWebApi(config);
public static IContainer Configure()
{
var builder = new ContainerBuilder();
// Register Credentials Service
builder.Register(_ => new CredentialsService(CredentialManagerConfiguration.LoadFromWebConfig()))
.As<CredentialsService>().SingleInstance();
// Register our DatabaseContext
builder.RegisterType<DatabaseContext>().AsSelf().InstancePerRequest();
// Register the CredentialManagerConfiguration using the web.config
builder.Register(_ => CredentialManagerConfiguration.LoadFromWebConfig()).AsSelf().SingleInstance();
// Register the EmailConfiguration using the web.config
builder.Register(_ => EmailConfiguration.LoadFromWebConfig()).AsSelf().SingleInstance();
// Register the EmailClient using the EmailConfiguration from the web.config
builder.RegisterType<EmailRepo>().As<IEmailRepo>().SingleInstance();
// Register the UnitOfWork using the DatabaseContext, FileTemplates and EmailClient
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().AsSelf()
.WithParameter("templateFileFolder", _fileTemplateBaseDirectory)
.WithParameter("downloadDir", _fileDownloadBaseDirectory)
.InstancePerRequest();
// Register the ScriptExecutionService using the DownloadDir and CredentialManagerConfiguration from the web.config
builder.RegisterType<ScriptExecutionHost>().AsSelf().WithParameter("fileDownloadBaseDirectory", _fileDownloadBaseDirectory).SingleInstance().AutoActivate();
// Register your Web API controllers.
var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// OPTIONAL: Register the Autofac model binder provider.
builder.RegisterWebApiModelBinderProvider();
builder.RegisterHttpRequestMessage(GlobalConfiguration.Configuration);
return builder.Build();
}
public ScriptsController(IUnitOfWork unitOfWork, ScriptExecutionHost scriptExecutionHost) : base(unitOfWork)
{
_unitOfWork = unitOfWork;
_adService = new ActiveDirectoryService(new ActiveDirectoryConfiguration());
_scripExecutionHost = scriptExecutionHost;
}
public class ScriptExecutionHost : IRegisteredObject
{
...
public ScriptExecutionHost(string fileDownloadBaseDirectory, CredentialManagerConfiguration credentialManagerConfiguration, IEmailRepo emailRepo)
{
// Register ourself to the hosting environment to be able to shut down gracefully
// This is necessary to ensure we can finish our work before the application pool is recycled
HostingEnvironment.RegisterObject(this);
_fileDownloadBaseDirectory = fileDownloadBaseDirectory;
_credentialManagerConfiguration = credentialManagerConfiguration;
_emailRepo = emailRepo;
_logger.Debug("ScriptExecutionHost initialized.");
_logger.Debug("File download base directory: {0}", _fileDownloadBaseDirectory);
// I used this to check if Autofac truly creates a new instance of this class every time.
initTime = DateTime.Now;
}