繁体   English   中英

如何在C#中设置DI / IoC和/或工厂模式设计

[英]How to set up DI / IoC and/or Factory pattern design in C#

我有一个需要SSH连接的设计,以便到达命令行界面来运行某些系统/功能级别的测试自动化。 可能有几种不同类型的SSH客户端:

  • 直接连接到普通的C / Bash shell
  • 在VM内或通过网关服务器等进行隧道连接/转发连接
  • 登录后需要从shell启动特定命令行调试接口的连接
  • 等等

我在使用Visual Studio的C#下使用SSH.NET开源库作为NuGet包,并且在一个简单的连接,发出命令和读回StdOut和StdErr响应的情况下使所有内容工作。

我的问题是,我想在这里实现一些Session / Command层,并且不确定如何正确使用接口来实现它们。 我想使用DI / IoC将SshSessionSshCommand层相互分离,并与SSH.NET SshClientSshClient ,但是如何开始设计呢?

我已经阅读了很多关于DI / IoC的解释并使用IoC容器等实现了一些单元测试,但设置DI的核心方法仍然没有点击。 我认为我不需要一个IoC容器来实现它,但可能需要使用工厂模式甚至是其他一些我还不熟悉的模式。


例如,要创建多个客户端类型,具有不同的连接标准,我以为我需要类似的东西:

  • ISshSession接口
  • SshSessionBase : ISshSession作为基类
  • 然后为每个客户端创建使用SshSessionBase自定义类。

但那么DI实际上是如何运作的呢? 自定义类是否作为IsshSession对象注入到基类的构造函数中? 或者我是否需要另一个使用这些自定义类对象的工厂或执行程序类?

我可能会在这里混淆主题..我只是缺少将我正在阅读的内容转换为实际实现的内容 - 感谢任何帮助!

我不确定我是否了解您的设计,但一般方法可能如下:

  1. 考虑所有客户端连接处理程序共有的行为和结构元素,并提取基类或接口。 例如,可能存在Connect()Send(ICommand)方法。

  2. 考虑设计中其他组件的结构和行为元素,例如命令或记录器或其他任何组件。 结果将是某种基类库。

  3. 确定如何实例化连接类型的具体实例。 如果关于连接类型的决定依赖于一组参数,则可以使用工厂。 工厂将获取一组参数并返回连接类型实例。 工厂可以自己实现接口,因此可以由IoC本身(抽象工厂)解决。

工厂本身可以实例化具体类,但是您的连接类可以利用基于构造函数的注入来访问其他组件(记录器,帮助器等),因此您的工厂可以依赖IoC容器,例如:

更新 :正如Michael指出的那样,将容器传递到工厂可能很方便,但隐藏了工厂的具体依赖性。 虽然对于较小的应用程序可能没问题,但更好的方法是将所有连接类型依赖项传递给实例化实例的工厂。

class StandardConnectionFactory : IConnectionFactory
{
    private readonly IContainer iocContainer;

    public StandardConnectionFactory(IContainer iocContainer) 
    {
        this.iocContainer = iocContainer;
    }

    public IConnection Create(string param1, int param2, ...)
    {
         if (...) return iocContainer.Resolve<IFancySshConnection>();
         else return iocContainer.Resolve<IAnotherConnection>();
    }
} 
  1. 如果关于使用哪种连接类型的决定依赖于一些简单的枚举或字符串(例如,用户决定命令行参数使用什么连接),则某些IoC容器(例如Autofac)允许注册具有名称和解析的类用这个名字。 在这种情况下,您不需要工厂,最终可能会遇到以下情况:

(伪代码)

// Registration Process
containerBuilder.Register<FancySshConnection>().For<IConnection>().WithName("ssh");
containerBuilder.Register<FancyFtpConnection>().For<IConnection>().WitName("ftp");

// Resolve
var connection = container.ResolveByName("ftp")
  1. 当您通过显式工厂(3)或某些内置实例化(4)实现实例化连接的方法时,将自动注入IoC容器已知的连接类型的依赖关系。 例如,上面调用iocContainer.Resolve<IFancySshConnection>(); 将实例化具体的连接类型,查看其构造函数,尝试解析每个参数,注入它们,等等。 只要找到之前注册的依赖项,它就会爬上依赖树。 所以你基本上所要做的就是注册你的基类组件(2)。

  2. 如果事情变得更大,更复杂,你最终可能会注册。 一些IoC容器(我坚持使用Autofac示例因为我非常喜欢Autofac)提供了一种将注册拆分为模块的简便方法。 这允许将注册过程分配到不同的组件中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM