我刚开始迁移我的网络应用程序以充分使用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的新手,我知道建议防止静态类。处理这种情况的好习惯是什么?我正在考虑将其转换为单身人士,但我不确定这是否是我最好的选择。
答案 0 :(得分:4)
这是我喜欢避免静态类的原因之一 - 它们难以注入或反转控制。他们通常必须知道几个低级别课程的私密细节。由于它们是静态类,因此它们可以保留,因为它们已经可用于所有其他类,并且不需要注入。
我所做的一个技巧是创建一个委托给静态类的第二个类。然后,您可以将接口放到新类上,然后更容易进入IoC框架。
public static class StaticClass
{
public static object Method()
}
public class NonstaticClass : INewInterface
{
public object Method()
{
return StaticClass.Method();
}
}
这个重构的好处是你可以逐个方法,然后确定新的对象和接口。最终你可以摆脱原来的静态类。您还可以将新类注册为单例实例,以便一次只存在一个实例。
答案 1 :(得分:3)
在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应用程序的生命周期内,因为它是一个单例。因此,如果存储库保持数据库连接打开,则该连接将在相同的生命周期内保持打开状态。
出于这种原因,另一种生活方式是每个Web请求 - 换句话说,容器将根据Web请求创建一个SiteInfo类的新实例。每个网络请求的生活方式在another question中进行了讨论。
答案 2 :(得分:0)
您可以在容器中注册一个类的单个实例,因此它的行为类似于单例。容器每次都为您提供相同的实例。