【问题标题】:Assigning properties on class dependencies在类依赖项上分配属性
【发布时间】:2012-03-22 14:36:58
【问题描述】:

假设我有一个将 IFileLogger 作为构造函数参数的类。

public MyClass : IClass
{
    private IFileLogger Logger;
    public MyClass(IFileLogger Logger)
    {
        this.Logger = Logger;
    }
}

在那个类的某个地方它调用Logger.Write("Data");

IFileLogger 有一个 DirectoryPath 属性;

需要设置此项,以便 IFileLogger 知道将文件写入何处。

这是如何设置的?

我的想法是在类上设置一个属性,然后在构造函数中设置 IFileLogger.DirectoryPath = this.DirectoryPath。

这似乎是错误的,因为 IClass 需要在其中包含属性,并且您最终会创建一个仅在底层需要的属性链。

你能帮助那些只见树木不见森林的人吗?您还会编写测试以及如何确定 IFileLogger 是否填充了其 DirectoryPath?

【问题讨论】:

    标签: c# .net unit-testing design-patterns tdd


    【解决方案1】:

    我是否可以建议您的界面设计是这里的问题,而您的问题是气味的指示?

    IFileLogger 表示您的类所依赖的接口。因此,查看界面我们看到有一个Write 方法。问题是,MyClass 并不真正关心日志记录是如何发生的,只是它符合接口。话虽如此,MyClass 需要知道目录位置才能告诉IFileLogger 如何完成工作的想法告诉您责任放错了位置。

    什么代码需要IFileLogger?记录,对吧?让我们稍微重构一下代码并实现满足客户端需求的接口MyClass。他不在乎如何记录日志,只关心它发生。

    改为将接口重命名为ILogger

    public MyClass : IClass
    {
        private ILogger Logger;
        public MyClass(ILogger Logger)
        {
            this.Logger = Logger;
        }
    }
    

    现在在此类中的任何地方都没有对“文件”的引用,这使得目录设置不属于此处变得更加明显。它属于哪里?可能在FileLogger 本身。

    使用依赖注入会给你留下类似的东西:

    main() {
      // Poor man's DI, no frameworks here
      var logger = new FileLogger("some/directory");
      var instance = new MyClass(logger);
      return instance.DoSomethingUsefulThatEventuallyGetsLogged();
    }
    

    希望有帮助!

    布兰登

    【讨论】:

      【解决方案2】:

      一般来说,我会说你的对象一旦构建就应该可以使用了,而不得不调用其他方法/属性来准备它只是令人困惑。所以 Logger 在将它传递给 MyClass 之前应该已经设置了它的 DirectoryPath 属性。例如:

      SomeInitialisationMethod
          ()
      {
          // or use IOC "factory" to create necessary concrete version.
          IFileLogger logger = new LoggerVariant("path");
      
          // MyClass can now use the ready to use logger. If we need to set the DirectoryPath, we can do it on this calling stack through the logger. 
          MyClass myClass = new MyClass(logger);
      

      【讨论】:

      • 如果 MyClass 即 IClass 是具有 InitlisationMethod 的类的构造函数参数怎么办?这就是我的代码的样子
      【解决方案3】:

      您如何以及在哪里实例化 IFileLogger,这听起来是设置其属性的地方。

        builder.RegisterType<FileLogger>().WithParameter(new NamedParameter("directoryPath", @"c:\temp")).As<IFileLogger>();
      

      使用此配置,任何时候您将使用该构建器来解析 IFileLogger,它将使用“c:\Temp”作为目录路径。

      【讨论】:

      • 您是否尝试使用 container.Resolve(new NamedParameter("dirPath",@"c:\temp"));
      • 不,我想这可行,但我需要一个包含容器的静态类
      • 这是否意味着当 IOC 创建 IFileLogger 的实例时,它将始终使用该参数?
      猜你喜欢
      • 2013-01-04
      • 2013-02-25
      • 2023-03-26
      • 1970-01-01
      • 2012-02-01
      • 2017-03-23
      • 2011-01-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多