【问题标题】:IoC logger with parameters带参数的 IoC 记录器
【发布时间】:2016-09-29 09:16:06
【问题描述】:

我目前正在使用 IoC 概念(使用 WPF 应用程序),我还没有决定要使用的工具,因为我仍在努力掌握它,但我'对于如何配置每个组件的特定参数感到困惑。

我了解您如何在配置文件中定义相关库,以及它将如何确定应用应该使用哪个库以及它的生命周期应该是多少,但是每个库需要自己的一组特定参数。

你从哪里得到这些,你什么时候传递它们?

以您的典型记录器为例。

我有如下界面:

public interface ILogger
{
    void Write(string message);
}

我有记录器类本身:

public class Logger : ILogger
{
    private readonly ILogger _logger;

    public Logger (ILogger logger)
    {
        _logger = logger;
    }

    public void Write(string message)
    {
        _logger.Write(message);
    }
}

然后我定义了多个记录器,每个记录器都需要自己的参数,所以我实现了以下内容:

a) 数据库记录器:需要连接字符串,以便我可以将消息记录到数据库。

public void LoggerDb: ILogger
{
    public void Write(string message)
    {
    }

    public ConnectionString {get; set;}
}

b) 文件记录器:需要一个文件名,以便我可以将我的消息记录到相关的日志文件中。

public void LoggerFile: ILogger
{
    public void Write(string message)
    {

    }

    public Filename {get; set;}
}

c) 控制台记录器: 不需要任何参数,因为我只想将消息输出到控制台窗口。

public void LoggerConsole: ILogger
{
    public void Write(string message)
    {
    }
}

在我的控制台测试应用程序中,我的 Program.cs 中有以下代码:

static void Main(string[] args)
{
    string logTypeId = "d";
    ILogger logType;

    if (logTypeId == "d")
    {
        logType = new LoggerDb("Data Source=....");
    }
    else if (logTypeId == "f"
    {
        logType = new LoggerFile("c:\\mylog.txt");
    }
    else
    {
        logType = new LoggerConsole();
    }

    Logger logger = new Logger(logType);

    logger.Write("Message 1");
    logger.Write("Message 2");
    logger.Write("Message 3");
}

我知道如果我使用 IoC 工具,代码将不会是这样。我只是想强调我想要实现的目标,并且我正在尝试回答以下问题:

  1. 这是否可以使用 IoC 工具来实现,即根据 app.config 的 IoC 部分中使用/定义的记录器类型传递特定参数?

  2. 这是正确的方法,即拥有具有自己构造函数参数的特定记录器吗?如果不是,你能解释一下为什么以及什么应该是正确的方法。我不介意您使用的 IoC 工具。我只是想了解这应该怎么做。

  3. 这些附加参数应该存储在 app.config 中的什么位置?

【问题讨论】:

  • “我知道如果我使用 IoC 工具,代码将不会是这样。”这是不正确的。即使您使用 DI 库,您所做的是一种有效的方法。您的Main 方法是Composition Root,您还可以在此处配置DI 库。在使用 DI 库的情况下,您的代码可能看起来完全一样。

标签: c# dependency-injection inversion-of-control ioc-container


【解决方案1】:

首先,请注意,为了通过 IoC 实现 DI,绝不需要在配置文件中配置您的容器(尽管它肯定是一个选项,并且许多容器都支持它)。

如今,大多数 IoC 容器还允许您在代码中指定设置。所以我想答案是:这真的取决于你计划使用的 IoC 容器。我的观点:尽可能避免基于xml的配置;如果您问我,维护通常很痛苦并且几乎没有价值。在基于代码的配置中,您仍然可以从 app.config 或其他中引用配置参数。

您也可以转过头来:是否需要将容器配置放在单独的文件中(以及为什么)?如果是,请寻找能够很好地支持此功能的容器。但大多数人都这样做。

使用基于代码的 DSL 的一些配置示例:

xml配置的一些例子:

【讨论】:

  • 感谢您的详细回答。我会看看你的链接,但你会用什么来代替基于 xml 的配置文件,为什么它没有带来什么价值。另外,当您说基于代码的配置时,您是指使用Properties.Default.xxx 访问数据吗?
  • 我忘了在我的问题中问一件事。例如,在 FileLogger 的情况下,可以在运行时更改“文件名”属性,而不是通过构造函数,以防我需要在运行时更改文件名,即基于特定进程创建文件名,每个进程都有自己的日志文件,文件名不同,但使用相同的记录器?谢谢。
  • 我强烈建议阅读 Autofac 模块的文档(查看示例)。至于你的问题,这确实是一个与依赖注入关系不大的设计问题。
  • 我对它们中的任何一个都不熟悉,所以我发现它(目前)令人困惑,并且结构图提供的示例不起作用,但希望事情会顺利进行,我会弄清楚的。我的主要目标是我希望能够切换库(例如上面的记录器示例)或在运行时添加新库,而无需重新编译我们的应用程序。顺便问一下,您知道 StructureMap 和 MvvmLight 简单 IoC 之类的区别吗?
  • SimpleIoC 是一个非常基础的容器,它没有高级生命周期管理或拦截功能。
【解决方案2】:

这取决于;)

  1. 我不能代表所有的 DependencyInjection 工具,但其中许多应该支持此功能。
  2. 我没有看到任何反对这一点的东西。如果你想显式调用不同的 Logger,你可以这样做。但是你也可以使用某种 LogListeners。一个用于数据库,一个用于文件,依此类推。而您的 Logger 只是将 LogMessage 委托给所有 Logger。但这取决于您想要或需要什么;)
  3. 这也取决于 Logger 的实现。将 ConnectionString 存储在配置中是很常见的。其他参数太具体了,不过你也可以把它们存到config里。

【讨论】:

  • 对不起,如果我不清楚,但我不想同时调用不同的记录器。如果需要,我只想允许从一个切换到另一个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
相关资源
最近更新 更多