2010-03-26 31 views
23

只是想让我的头仍然围绕着国际奥委会的原则。国际奥委会 - 应使用静态辅助方法的类与IOC连接?

Q1:静态方法 - 应该将具有静态辅助方法的util类与IOC连接起来吗?

例如,如果我有一个具有多个静态方法的HttpUtils类,我应该试图通过IOC将它传递给其他业务逻辑类吗?针对此问题

关注可能是:

Q2:单身 - 什么之类的东西记录在那里你可以通常通过Logger.getInstance访问它()呼叫类型。您通常会保持原样,而不是使用IOC将记录器注入需要它的业务类中?

问题3:静态类 - 我还没有真正使用过这个概念,但是如果您正在转向基于IOC的方法,您通常会如何处理这个问题。

在此先感谢。

回答

30

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

让我们使用实用工具类为例:

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

在非国际奥委会为重点的应用程序,你可以直接使用该方法:

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

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

然而,夫妇的定义DoStuff直接执行。国际奥委会致力于离婚的种种细节,所以不是我们定义自身的操作:

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

这样可以使FooHttpUtilsDoStuff这个概念的实现者现在是一个配置细节,而不是一个固有的依赖关系(就像静态方法一样)。

请注意,Foo不知道它的IDoesStuff是否为单例。该生存期是也是的配置细节,而不是Foo的固有细节。

总而言之,IoC和static一般都是不一致的,因为IoC促进变化,根据定义,static可以阻止它。在你的构造函数中声明你的依赖关系,你会发现你几乎从来没有使用过static的功能。

+0

感谢Bryan - 这是否意味着每次都可能会有更多的IOC构造事物(例如记录器)的开销?同样对于utils类型类,我想知道这会不会在重构助手类中的辅助函数时使得重构更难? (我自己使用ReSharper) - 谢谢 – Greg 2010-03-26 21:17:41

+0

大多数IoC容器允许某种范围的范围。通过这个,我的意思是说明你的对象是每次(工厂)创建的,每个上下文(工作单元)创建一次,还是每个应用程序(单例)一次。这意味着您可以注册记录器,使其仅创建一次。 – 2010-03-26 21:28:05

+2

最终你想消除公用事业类。每个类中的每个方法都与上面的“HttpUtils.DoStuff”方法具有相同的耦合问题。出于这个原因,你不想要求任何*代码直接依赖于'static'成员。相反,将'HttpUtils.DoStuff'的主体放在'IDoesStuff'后面,并从'HttpUtils'完全删除该方法。现在,任何可能调用静态方法的类都可以在其构造函数中接受'IDoesStuff'。维奥拉:不再需要公用事业类! – 2010-03-26 21:37:51

6

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

1)辅助类的静态方法 - 不,这些通常不会被IoC注入。通常他们是无状态的公用事业。

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

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

如果该实用程序是不是真的无状态(例如取决于HttpContext.Current),那么你应该做的依赖性明确通过注射它,而不是让该实用程序的静态。

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

因此,单身躯干停止是一个单独的问题,必须编入类(以及不必担心的类有多个问题),它成为IoC容器的关注点。你不会像“私有构造函数”和方法那样将类“作为单例”编码,你只需将它编码为主要关注点,而IoC容器的配置指定它是否是单例,或者某处介于两者之间,如每个线程一个实例。

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

2

按定义静态方法不需要实例。 DI/IOC的目标是满足具体类的接口,并且考虑到静态类和静态方法根据定义不能实现接口或扩展类,这个问题是没有意义的。 Theres在传递helper类方面毫无意义,因为不需要实例来使用静态方法。即使没有实例,您的代码也会始终执行相同的静态帮助程序方法。

在IOC/DI驱动的应用程序中,可以定义接口并且至少有一个实现。它关于管理实例及其依赖关系。

0

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

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

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

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

想一想,为什么不呢?

+0

这是一个答案,或只是对问题的评论? – 2013-11-05 18:57:24

相关问题