首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >当我转向依赖注入时,使用语句会发生什么情况?

当我转向依赖注入时,使用语句会发生什么情况?
EN

Stack Overflow用户
提问于 2012-09-11 06:23:24
回答 3查看 3.7K关注 0票数 25

我目前使用的代码如下:

代码语言:javascript
复制
public class MyProvider
{
    public MyProvider()
    {
    }

    public void Fetch()
    {
        using (PopClient popClient = new PopClient())
        {
            ....
        }
    }
}

因为我希望能够对Fetch方法进行单元测试,并且不能模拟PopClient,所以我创建了一个调用PopClient的接口和包装类。我更新的代码看起来像这样:

代码语言:javascript
复制
public class MyProvider
{
    private readonly IPopClient popClient;

    public MyProvider(IPopClient popClient)
    {
        this.popClient = popClient;
    }

    public void Fetch()
    {
        using (var pop3 = popClient)
        {
            ....
        }
    }
}

我正在使用Ninject进行依赖注入,我不太确定using语句在更新后的代码中会有什么样的效果,因为Ninject已经创建了PopClient的一个实例并将其注入到构造函数中。

using语句会处理掉pop3对象而不去管popClient对象吗?还是说using语句会干扰Ninject?

在这种情况下,正确的方法是什么?任何洞察力都会非常有帮助。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-11 06:31:27

pop3变量将被赋予与popClient相同的对IPopClient对象的引用,因此当using语句结束时,由本地变量和实例变量引用的对象将是Dispose()d,这可能会使其处于不一致的状态以供进一步使用。

如果你想使用多个IPopClient实例,每个Fetch()调用一个,你应该做的是注入一个“工厂方法”:

代码语言:javascript
复制
public class MyProvider
{
    private readonly Func<IPopClient> createPopClient;

    public MyProvider(Func<IPopClient> popClientFactory)
    {
        this.createPopClient = popClientFactory;
    }

    public void Fetch()
    {
        using (var pop3 = createPopClient())
        {
            ....
        }
    }
}

现在,当您调用Fetch()时,它将执行工厂方法,该方法将返回对IPopClient的新引用,可以使用该引用,然后在不影响对该方法的任何其他调用的情况下将其清除。

AutoFac支持为注册类型注入工厂方法,而不需要任何额外的设置(我想,这就是它的名字的由来);我相信在配置一个()=>new PopClient()容器时,你需要显式地注册一个"getter“作为给定返回类型的工厂方法(这可以是一个简单的lambda解析方法,也可以使用对容器解析方法的调用)。

票数 18
EN

Stack Overflow用户

发布于 2012-09-11 06:26:04

在设置绑定时,声明作用域:

https://github.com/ninject/ninject/wiki/Object-Scopes

Ninject会在它为你创建的对象上调用dispose,所以确保你把dispose方法写在你给Ninject去处理的任何对象中。

票数 1
EN

Stack Overflow用户

发布于 2021-07-30 15:43:20

我喜欢@KeithS的回答,但我想用ConfigureServices、.NET核心依赖注入和MailKit.Net.Smtp添加一些更新。

https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection

给定下面的类:

代码语言:javascript
复制
public class MailService
{
    private readonly SmtpSettings _settings;
    private readonly Func<ISmtpClient> _smtpClientFactory;

    public MailService(SmtpSettings settings, Func<ISmtpClient> smtpClientFactory)
    {
        _settings = settings;
        _smtpClientFactory = smtpClientFactory;
    }

    public async Task SendEmailAsync(string to, string subject, MimeEntity body, CancellationToken cancellationToken = default)
    {
        var message = new MimeMessage();
        message.From.Add(MailboxAddress.Parse(_settings.UserName));
        message.To.Add(MailboxAddress.Parse(to));
        message.Subject = subject;
        message.Body = body;

        using (var smtpClient = _smtpClientFactory())
        {
            await smtpClient.ConnectAsync(_settings.Server, _settings.Port, SecureSocketOptions.StartTls, cancellationToken);
            await smtpClient.AuthenticateAsync(_settings.UserName, _settings.Password, cancellationToken);
            await smtpClient.SendAsync(message, cancellationToken);
            await smtpClient.DisconnectAsync(true, cancellationToken);
        }
    }
}

它可以像这样添加到ConfigureServices(IServiceCollection services)

代码语言:javascript
复制
services.AddTransient<ISmtpClient, SmtpClient>();
services.AddSingleton(provider =>
                 new Func<ISmtpClient>(() => provider.GetService<ISmtpClient>()));

Azure函数的完整Program.cs示例:

代码语言:javascript
复制
public static void Main()
{
    var host = new HostBuilder()
        .ConfigureFunctionsWorkerDefaults()
        .ConfigureAppConfiguration((hostContext, builder) =>
        {
            if (hostContext.HostingEnvironment.IsDevelopment())
            {
                builder.AddJsonFile("local.settings.json");
                //This will override any values added to local.settings.json - We will however follow the recommended approach for keeping secrets in dev 
                //https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows#register-the-user-secrets-configuration-source
                //builder.AddJsonFile("secret.settings.json");
                builder.AddUserSecrets<Program>();
            }

        })
        .ConfigureServices((hostContext, services) =>
        {
            var connectionString = hostContext.Configuration.GetConnectionString("DefaultConnection");
            services.AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(
                    connectionString,
                    sqlServerOptions => sqlServerOptions.CommandTimeout(600)));

            services.AddHttpClient();

            var configuration = hostContext.Configuration;

            var smtpSettings = new SmtpSettings();
            configuration.Bind("Smtp", smtpSettings);
            services.AddSingleton(smtpSettings);

            services.AddTransient<ISmtpClient, SmtpClient>();

            services.AddSingleton(provider =>
                 new Func<ISmtpClient>(() => provider.GetService<ISmtpClient>()));

            services.AddTransient<MailService>();
        })
        .Build();

    host.Run();
}

用于注册和解析Func<T>的源代码:

https://stackoverflow.com/a/43763284/3850405

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12360271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档