在类依赖项上分配属性

时间:2012-03-22 14:36:59

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

假设我有一个类,它将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?

3 个答案:

答案 0 :(得分:0)

如何以及在何处实例化IFileLogger,它听起来是设置其属性的地方。

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

使用此配置,只要您使用该构建器解析IFileLogger,它就会使用“c:\ Temp”作为directoryPath。

答案 1 :(得分:0)

一般来说,我会说你的对象应该在构造之后就可以使用了,并且必须调用其他方法/属性才能让它准备就绪,这简直令人困惑。因此Logger在将其传递给MyClass之前应该已经设置了DirectoryPath属性。 E.g:

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);

答案 2 :(得分:0)

我可能会建议你的界面设计是问题,你的问题是气味的指示吗?

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();
}

希望有所帮助!

布兰登