IOC - 具有静态帮助方法的util类是否应该与IOC连接?

时间:2010-03-26 20:46:12

标签: static inversion-of-control ioc-container ninject instance

只是试着继续了解IOC原则。

Q1:静态方法 - 是否应将具有静态帮助方法的util类与IOC连接?

例如,如果我有一个带有许多静态方法的HttpUtils类,我是否应该尝试通过IOC将其传递给其他业务逻辑类?

关于这个的问题可能是:

Q2:单身人士 - 通过Logger.getInstance()类型调用记录您通常可以访问它的内容。您是否通常将其保留原样,并且不使用IOC将记录器注入需要它的业务类?

问题3:静态类 - 我还没有真正使用过这个概念,但如果您采用基于IOC的方法,是否有任何指导方针可以解决这个问题。

提前致谢。

4 个答案:

答案 0 :(得分:32)

关于IoC的有趣之处在于,用这种风格编写的对象通常与这些细节分离。

我们以实用程序类为例:

public class HttpUtils
{
    public static void DoStuff(int someValue)
    {
        // ...
    }
}

在非IoC专注的应用程序中,您可以直接使用该方法:

public class Foo
{
    public int Value { get; set; }

    public void DoStuff()
    {
        HttpUtils.DoStuff(Value);
    }
}

但是,它将DoStuff的定义直接与其实现相结合。 IoC努力将这些细节分开,所以我们自己定义操作:

public interface IDoesStuff
{
    void DoStuff(int someValue);
}

然后,我们在Foo留出空间让实施改变:

public class Foo
{
    private readonly IDoesStuff _doesStuff;

    public Foo(IDoesStuff doesStuff)
    {
        _doesStuff = doesStuff;
    }

    public int Value { get; set; }

    public void DoStuff()
    {
        _doesStuff.DoStuff(Value);
    }
}

这会将FooHttpUtils分开。 DoStuff概念的实现者现在是一个配置细节,而不是固有的依赖(就像静态方法一样)。

请注意,Foo不知道其IDoesStuff是否是单身人士。该生命周期也是配置细节,而不是Foo的固有细节。

总而言之,IoC和static通常不一致,因为IoC促进了变化,而static,根据定义,它会阻止它。在构造函数中声明您的依赖项,您会发现几乎从未使用过static函数。

答案 1 :(得分:8)

IoC容器通常用于注入具有状态的对象;或者具有多个实现的类或接口,即使第二个实现是用于测试目的的模拟。如果这些都不是真的,那么通过注入它就没有任何好处。这些天最常见的习惯是让你的类面向真实和模拟实现都可以实现的接口。

1)辅助类上的静态方法 - 不,这些通常不会被IoC注入。通常它们是无状态实用程序。

使用一个非常简单的示例,您不需要两个版本的名为StringUtils.Reverse()的实用程序方法。你只需要一个,你可以很容易地围绕它编写测试,因为它没有状态或依赖,所以嘲笑它绝对没有任何好处。示例测试:

string reversedString = StringUtils.Reverse("input");
Assert.AreEqual("tupni", reversedString)

如果该实用程序实际上不是无状态的(例如依赖于HttpContext.Current),那么您应该通过注入它来使接口显式化,而不是使该实用程序保持静态。

2)单身人士:通常是的,注入单身人士。但IoC的一个好处是你不用担心是否只有一个东西。通过使用IoC,您可以获得实例化的灵活性。每次将特定类型作为单例或新实例的决定成为IoC容器配置的一部分,代码中的其他任何内容都不需要更改。

因此,singleton-hood不再是一个必须被编码到类中的单独关注点(当它们不必要时会有多个关注点的类很糟糕),它就成了IoC容器的关注点。你不用“私有构造函数”和public static GetInstance()方法之类的任何特殊代码将“作为单例”编码,你只需要为主要问题编写代码,而IoC容器的配置指定它是单例还是不是,或介于两者之间,就像每个线程一个实例一样。

3)静态类 - 是静态方法的自然之家。考虑在适当的地方制作静态方法扩展方法。您无法注入这些类,因为您无法创建它们。使用静态类使得过程不是面向对象的代码。这对小辅助方法来说并不坏,但如果大多数代码都是这样,那么你就不会使用.Net平台强大的OO功能。

答案 2 :(得分:2)

根据定义,静态方法不需要实例。 DI / IOC旨在满足具体类的接口,并且假定您的静态类及其静态方法定义不能实现接口或扩展类,这个问题毫无意义。传递助手类没有意义,因为一个人不需要实例来使用静态方法。即使没有实例,代码也总是会执行相同的静态helperr方法。

在IOC / DI供电的应用程序中,可以定义接口并至少具有一个实现。它完全是关于管理实例及其依赖项。

答案 3 :(得分:0)

当实用程序类需要访问数据库时,就会出现这种困境。虽然db访问器需要Ioc,但实用程序类必须使用Ioc,因此它不能是静态的。

但我真的希望实用程序类是静态的,因此很容易被消费。我不想填充需要实用程序类的每个使用类的构造函数。

消费类本身甚至可能不需要自己进行数据库访问。所以我不想注入db访问器并将其传递给实用程序类。

猜猜现在还没有完美的解决方案。有一天,我希望我们更进一步,除了构造函数/属性注入,还有“全局上下文注入/配置”或“静态注入”,将Ioc应用于对象创建之外。

想想,为什么不呢?