【问题标题】:How do i handle static classes while using IOC使用 IOC 时如何处理静态类
【发布时间】:2010-06-27 13:17:34
【问题描述】:

我刚刚开始迁移我的 Web 应用程序以充分使用 Windsor IOC。这是我遇到的一个小问题;

我有几个静态类,用于存储一些应用程序级别的全局值

EG(类的简化版):

public static class SiteInfo
{
        public static Language Language = (Language)byte.Parse(SiteInfo.Val("language"));
        public static string Code = Site.Code;
        public static string Name = Site.Name;

        public static SiteCachedData CachedData { get; set; }
        public static Site Site { get; set; }

       public static void Init()
       {
          //Get site info from DB here
          //I need to inject _SiteRepository here but I can't 
          //since I don't have access to the constructor
       }
}

我是 IOC 新手,我知道建议不要使用静态类。处理这种情况的好习惯是什么?我正在考虑将其转换为单例,但我不确定这是否是我最好的选择。

【问题讨论】:

    标签: c# .net ioc-container


    【解决方案1】:

    这是我喜欢避免使用静态类的原因之一——它们很难注入或反转控制。他们通常必须知道几个低级课程的私密细节。由于它们是静态类,因此您可以保留它们,因为它们已经可供所有其他类使用并且不需要注入。

    我做过的一个技巧是创建第二个代表静态类的类。然后,您可以将接口放到新类上,并更轻松地进入 IoC 框架。

    public static class StaticClass   
    {  
        public static object Method()   
    }
    
    public class NonstaticClass : INewInterface  
    {  
        public object Method()  
        {  
            return StaticClass.Method();  
        }  
    }
    

    这个重构的好处是你可以一个接一个地去,然后在你去的时候确定新的对象和接口。最终你也许能够摆脱原来的静态类。您还可以将新类注册为单例实例,以便一次只存在一个实例。

    【讨论】:

      【解决方案2】:

      在 IoC 容器的上下文中,说“将其转换为单例”有点模棱两可。如果您指的是singleton design pattern,您可能不应该那样做,因为在 IoC 世界中有更好的选择。

      IoC 容器执行两个主要角色:解决组件之间的依赖关系,以及管理组件的生命周期。容器通过决定何时创建和销毁组件实例来管理其组件的生命周期。

      例如,当您调用container.Resolve<SiteInfo>() 时,容器必须决定是重新使用现有的 SiteInfo 实例还是创建一个新实例。容器如何决定?好吧,当您向容器注册 SiteInfo 时,您可以告诉容器您希望它的行为方式。如果将其注册为 Singleton,则容器只会在第一次调用 container.Resolve<SiteInfo>() 时创建 SiteInfo 实例;在随后的调用中,它会重新使用现有的 SiteInfo 实例。

      与单例模式相比,这种技术的优势在于灵活性。如果您使用设计模式,您的 SiteInfo 类将永远是一个单例(除非您重构)。通过使用容器管理生命周期,您可以稍后改变主意,只需更改容器注册码。组件的消费者不需要(也不应该)关心容器是为他们提供新实例还是重复使用现有实例 - 他们只需调用container.Resolve()

      我对 Windsor 不熟悉(我使用 Autofac),但看起来您有两种方法可以将组件注册为单例(如果这是错误的,我相信有人会纠正我):

      container.AddComponentLifeStyle<SiteInfo>(LifestyleType.Singleton)
      

      或者,

      container.Register( Component.For<SiteInfo>()
                          .LifeStyle.Singleton );
      

      但是,请注意。在您的示例中,您的 SiteInfo 类依赖于 _SiteRepository 类。因此,您还需要在容器中注册一个 _SiteRepository 实例作为单例,以便在容器解析 SiteInfo 时它可用。这个 _SiteRepository 实例将在容器的生命周期内保留在内存中,即在 Web 应用程序的生命周期内,因为它是一个单例。因此,如果存储库保持数据库连接打开,则该连接将在相同的生命周期内保持打开状态。

      出于这种原因,另一种生活方式是每个网络请求 - 换句话说,容器将为每个网络请求创建一次 SiteInfo 类的新实例。在another question 中讨论了每个网络请求的生活方式。

      【讨论】:

        【解决方案3】:

        您可以在容器中注册一个类的单个实例,因此它的行为就像一个单例。容器每次都会为您提供相同的实例。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-10
          • 2011-02-06
          • 1970-01-01
          • 1970-01-01
          • 2015-09-22
          • 1970-01-01
          相关资源
          最近更新 更多