依赖注入 - 何时在 Web 应用程序中使用单例范围

con*_*att 5 .net dependency-injection inversion-of-control simple-injector asp.net-web-api

在我的 .NET Web APIv2 项目中,我发现自己将所有注入服务的范围标记为Singleton.

我正在使用Simple Injector DI 框架(这对我的具体问题并不重要)。

这是一个简化的示例:

public class SqlConnectionFactory : IDbConnectionFactory
{
    public async Task<SqlConnection> GetOpenSqlConnectionAsync()
    {
        var connection = new SqlConnection("connstring");

        await connection.OpenAsync();

        return connection;
    }
}


public class UserService : IUserService
{
    private IDbConnectionFactory DbConnectionFactory { get; set; }

    public UserService(IDbConnectionFactory dbConnectionFactory)
    {
        DbConnectionFactory = dbConnectionFactory;
    }

    public async Task AddAsync(AddUserDto data)
    {
        using (SqlConnection connection = await DbConnectionFactory.GetOpenSqlConnectionAsync())
        {
            // Create a glorious SqlCommand...
            await cmd.ExecuteNonQueryAsync();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的其他一些服务包括一些加密类,它们不包含任何状态,并且很容易成为静态类。

这是简单注入代码,仅供完成:

        var container = new Container();

        container.Register<IDbConnectionFactory, SqlConnectionFactory>(Lifestyle.Singleton);
        container.Register<IUserService, UserService>(Lifestyle.Singleton);
Run Code Online (Sandbox Code Playgroud)

根据我创建数据库连接的方式,在我看来,单例对于我的SqlConnectionFactory班级以及我的UserService班级来说都很好,但如果我错了,请纠正我。

这让我问,你什么时候会(或不会)使用单例范围来注入服务?如果你可以使用 Singleton,为什么不呢?不必为每个 Web 请求线程或方法的入口(瞬态)实例化新实例,难道不会带来性能优势吗?

Mar*_*ann 1

作为一般规则,对线程安全类使用 Singleton 生命周期。如果单个实例也可以完成这项工作,那么就没有理由一直创建新实例。但是,您还需要避免强制依赖项。

就OP而言,在我看来好像所有类都是无状态的(因此是线程安全的),所以单例生命周期对我来说看起来很好。

使用 DI 容器时,生命周期不匹配可能很难发现,但使用 Pure DI 时,更容易检测到。这是我更喜欢Pure DI 的众多原因之一。