【问题标题】:Dependency injection and many implementations of interface依赖注入和接口的许多实现
【发布时间】:2013-11-25 13:28:34
【问题描述】:

在我的项目中使用依赖注入有一个小问题。为了描述问题,我将使用简单的示例。假设我正在编写记录器应用程序,并且我的最终用户能够选择是否应将日志保存到文件或写入控制台。用户通过在运行的应用程序中选择复选框来控制它。他可以选择两者或只选择一个。选择后,他单击“LOG”按钮执行操作。 现在,根据我对 DI 的了解,我应该创建接口:

public interface ILogger
{ 
   void log();
}

还有两个实现

public class ConsoleLogger : ILogger
{
    public void log()
    {
      ...
    }
}

public class FileLogger : ILogger
{
    public void log()
    {
      ...
    }
}

我知道我可以在例如统一容器中注册这两个实现,并通过使用表在构造函数中获取它们,但是我无法确定哪些实现是 FileLogger,哪些是 ConsoleLogger(如果用户只选择一个复选框)

第二个选项是使用服务定位器模式通过名称解析来自 ioc 的实现。不知道是不是好办法

在我的实际应用程序中,我将有两个以上的选项,并且每个选项都会有很多共享接口。

也许使用 MEF 更好?

应用程序将使用 WPF + PRISM 编写。

【问题讨论】:

    标签: c# wpf design-patterns dependency-injection inversion-of-control


    【解决方案1】:

    我通常这样做的方式是让你的类依赖于ILoggerFactory,它可以创建给定名称的ILogger 实例。

    工厂实现LoggerFactory 将保存容器的内核并能够按名称解析组件。

    请注意,工厂接口如何只告诉您它可以创建对象 - 它不会为您提供任何有关任何底层内核或 DI 框架的提示 - 工厂实现是知道这些细节的那个。

    类似这样的:

    public class MyLoggingClass
    {
        private readonly ILoggerFactory _loggerFactorty;
    
        public MyLoggingClass(ILoggerFactory factory)
        {
            _loggerFactorty = factory;
    
            var fileLogger = _loggerFactorty.Create("fileLogger");
            var consoleLogger = _loggerFactorty.Create("consoleLogger");
        }
    }
    
    
    public class LoggerFactory : ILoggerFactory
    {
        public ILogger Create(string key)
        {
            return kernel.Resolve<ILogger>(key);
        }
    }
    

    Castle Windsor 等框架甚至免费为您提供这些工厂:您甚至不必编写其实现。

    【讨论】:

    • 我明白我所有的工厂都应该是我的作文根的一部分。谢谢!
    【解决方案2】:

    服务定位器模式现在是一种反模式,不应该使用。

    在您的情况下,最好使用Strategy design pattern,因为您是在运行时动态创建对象。

    依赖注入和策略模式之间的区别很微妙,但确实存在。欲了解更多信息:

    Strategy Pattern vs Dependency Injection

    What is the difference between Strategy pattern and Dependency Injection?

    要动态创建对象,您可以使用factory method 设计模式或abstract factory。

    【讨论】:

      【解决方案3】:

      如果您想要的只是基本的 IOC 功能,我看不出创建自定义工厂的意义。如果您要使用 WPF 和 Prism 开发应用程序,一个好的方法是使用受支持的 IOC 容器之一。我经常使用 Unity,并且非常喜欢它。另一个受支持的版本是 MEF(如您所建议的)。

      它们都允许您使用名称解析接口。这是不错的做法,并提供了解决正确界面的结构化方法。

      要在 Unity 或 Mef 中使用 Prism,请参见此处:

      http://msdn.microsoft.com/en-us/library/gg430868(v=pandp.40).aspx

      【讨论】:

        猜你喜欢
        • 2018-09-23
        • 2015-10-18
        • 2020-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多