2010-06-27 44 views
4

我刚开始迁移我的Web应用程序以充分使用Windsor IOC。这是我遇到的一个小问题;如何在使用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 
     } 
} 

我是新来的国际奥委会和我的理解静态类建议被阻止。处理这种情况的最佳做法是什么?我正在考虑将其转换为单身人士,但我不确定这是否是我最好的选择。

回答

0

您可以在容器中注册一个类的单个instanec,因此它的行为类似于单例。容器每次都会给你相同的实例。

3

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

我所做的一个诀窍是创建一个委托给静态类的第二个类。然后,您可以将接口放到新类中,并更轻松地进入IoC框架。

public static class StaticClass 
{ 
    public static object Method() 
} 

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

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

3

在IoC容器的上下文中,说'将其转换为单例'有点含糊不清。如果你的意思是singleton design pattern,你可能不应这样做,因为IoC世界有更好的选择。

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

例如,当您致电container.Resolve<SiteInfo>()时,容器必须决定是重新使用现有SiteInfo实例还是创建一个新实例。容器如何决定?那么,当你向容器注册SiteInfo时,你可以告诉容器如何行为。如果您将其注册为Singleton,则该容器将仅在第一次调用container.Resolve<SiteInfo>()时创建SiteInfo实例;在后续调用中,它将重新使用现有的SiteInfo实例。

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

我不熟悉的温莎(我用Autofac),但它看起来像你必须注册一个组件作为一个单独的两种方法(我敢肯定有人会纠正我,如果这是错误的):

container.AddComponentLifeStyle<SiteInfo>(LifestyleType.Singleton) 

,或者

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

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

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