将运行时构造函数参数传递给Autofac的最佳方法是什么? [英] What is the best way to pass runtime constructor parameters to Autofac?

查看:232
本文介绍了将运行时构造函数参数传递给Autofac的最佳方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个通用的中间件软件(Windows服务),它将执行许多jobs ..如:

I am building a generic piece of middleware software (a windows service) that will perform many jobs.. such as:

  • 同步库存
  • 进口订单

我正在将C#与Windows Service配合使用,并使用Quartz.NET安排要运行的作业. 我也在使用AutoFac.

I am using C# with a Windows Service, and Quartz.NET to schedule the jobs to run. I am also using AutoFac.

据我了解,AutoFac依赖关系应在组合根目录下构建.很好.但是,我注入了某些服务,这些服务需要运行时参数(来自数据库的配置值).

From what I understand, AutoFac dependencies should be built at the composition root. This is fine..however, I have certain services that get injected which require runtime parameters (configuration values that come from the database).

例如:

  • 某些作业将连接到SFTP服务器,从而将连接详细信息作为键值对存储在数据库中
  • 某些作业将连接到远程API,从而将针对该作业的API身份验证详细信息存储在数据库中.

我已经对此进行了一些研究,一些替代方案基本上建议删除其中一些服务(例如SFTP客户端)的构造函数,并将其作为配置方法传递.

I've done some research on this and some alternatives basically suggest removing the constructor of some of these services (such as an SFTP client) and passing these as configuration methods..

不是客户端,而是诸如

SftpClient(string host, string username, string password, int timeoutInSeconds)

它将具有一个默认的构造函数和一个将其传递给它们的configure方法.

It would have a default constructor, and a configure method that you pass these in.

我根本不喜欢这样-这与我所学到的东西相违背,您应该尝试配置您的对象,以便通过构造函数使其处于一致状态.

I don't like this at all- it goes against what I've learnt in that you should try and configure your object so it is in a consistent state through the constructor.

最佳选择是什么? 我的JobFactory方法当前依赖于IComponentContext. 我已经看到了将参数传递给AutoFac来构造对象的方法,但是我读过的东西表明它并不理想. 仅仅使用我的工厂来更好

What are the best options? My JobFactory method currently takes on a dependancy on IComponentContext. I've seen there are ways to pass parameters to AutoFac to construct the object, but things I've read suggest that it is not ideal. Is it better to just use my Factory to

推荐答案

最简单的解决方案是注入工厂而不是实例.不要注入AutoFac容器本身(隐藏依赖项).只需编写一个简单的类.

The simplest solution is to inject a factory instead of an instance. Do not inject the AutoFac container itself (that hides dependencies). Just write a simple class.

class SftpClientFactory : ISftpClientFactory
{
    public SftpClient GetClient(string host, string userName, string password, int timeout)
    {
        return new SftpClient(host, userName, password, timeout);
    }
}

然后像这样注册它:

container.RegisterType<ISftpFactory, SftpFactory>();

在你的班上

class Example
{
    private readonly ISftpClientFactory _clientFactory;

    public Example(ISftpClientFactory injectedFactory)
    {
        _clientFactory = injectedFactory;
    }

    public void DoTheWork()
    {
        var client = _clientFactory.GetClient(host, userName, password, timeout);
    }
}

作为奖励,您现在可以完全控制对象的生命周期,这似乎对于sftp客户端可能很重要,该客户端可能包含非托管资源并且为Disposable:

As a bonus, you now have complete control of the object life cycle, which sounds like it could be important with an sftp client, which might hold a non-managed resource and be Disposable:

    public void DoTheWork()
    {
        using (var client = _clientFactory.GetClient(host, userName, password, timeout))
        {
            client.DownloadFile();
        } 
    }

此方案保留了控制的反转,您仍然保留单个组合根,仍然可以通过单元测试项目对客户端进行存根,并且仍可以获取依赖项的编译时解析.唯一的缺点是编写存根的工作量要多一些,因为您还必须编写存根工厂.

This scheme preserves the inversion of control, you still keep a single composition root, the client can still be stubbed by your unit test project, and you still get compile-time resolution of dependencies. The only down side is it is slightly more work to write the stub, since you have to write a stub factory too.

这篇关于将运行时构造函数参数传递给Autofac的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆