2011-09-27 102 views
3

我们使用Ninject作为IOC。Ninject和私人构造函数

我们所有的Repository对象都可以(也应该)被模拟进行单元测试。我希望强制所有开发人员在与存储库交互时只编写接口。对于这一点,我想使构造私人,营造建设静态访问工厂方法:

public class SomeRepository : ISomeRepository 
{ 
private SomeRepository() 
{ 
} 
public static ISomeRepository Create() 
{ 
    return StandardKernel.Get<ISomeRepository>(); 
} 
} 

问题就在于此:我怎么有Ninject创建实际的对象?我在同一个项目中拥有版本库接口和类

+0

[必填服务定位器链接。](http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx)在继续您的设计之前,我会阅读这两次 - 'StandardKernel.Get'看起来像一个服务定位器。我不会说“服务定位器在这里肯定是错误的”,但Mark Seemann会,而且如果我是你,我会相信他。 –

+1

为什么你想强制私人构造函数?没有冒犯,但我认为你应该相信你的开发人员,并简单地定义某些书面或口头传达,而不是过分复杂的事情与一个尴尬的设计... –

+0

@ default.kramer:完全同意文章,这就是为什么我不想陷入同样的陷阱。通过没有其他方式创建对象,我计划强制维护开发人员使用IOC而不是方向实例化 – Igorek

回答

2

我们最终与以下去:

public class SomeRepository : ISomeRepository 
{ 
private SomeRepository() 
{ 
} 
public static ISomeRepository CreateForIOC() 
{ 
    return new SomeRepository(); 
} 
} 

和加载模块期间,我们正在映射的StandardKernel的ISomeRepository接口CreateForIOC()方法。

这并不会阻止开发人员直接调用CreateForIOC,但至少强制他们a)代码到接口,b)意识到CreateForIOC()可能不是实例化对象时调用的正确方法,并且至少会询问一个关于它的问题从主导开发商

+0

除非我错误地理解了静态“构造函数”的原因,您可以使用内联func在映射接口时构造类。 'Kernel.Bind ()。ToMethod(具体=> {return new SomeRepository();});'。这样可以节省你在那里获得静态的麻烦。你的私有构造函数不得不消失,因为我认为你不能创建一个具有私有构造函数regadless的“新”实例,如果它是类中的静态方法或映射中的func。 – Nope

+0

静态CreateForIOC方法本身就在类中,因此它可以直接访问构造函数,即使它是私有的。 NInject不能创建一个只有一个辅助静态方法或一些工厂的私有构造函数的对象 – Igorek

+1

我没有意识到,因为我因为隐藏的构造函数而在Ninject调用上出现编译错误,所以我认为它对于静态方法也是如此。我今天学到了新东西,谢谢。关于实现,我仍然会尝试,而不是让类自己完成构建,只是使用Ninject方法来返回实现,只是我个人的偏好。希望你已经按照现在的顺序排列:) – Nope

1

为什么不只是将Ninject提供给需要它的任何对象的具体存储库呢?而不是私有构造函数或工厂方法。

+0

你能详细说明一下吗? – Igorek

+1

如果您将容器类型放置在容器中,然后根据容器中的存储库获取应用程序类实例,Ninject会自动将存储库实例提供给需要它的类型。这通常是calles“auto wire-up”,是DI/IoC容器值得学习和使用的一部分, –

0

它看起来像你试图使用单例模式。一般来说,单身模式被认为是反模式,主要是因为它阻碍了单元测试。依赖注入允许您通过配置创建单例,而不必使用单例模式。

我建议你改为将Ninject配置为在没有私有构造函数的情况下创建应用的单个实例。

+0

这不是Singleton ... –

+0

@AustinSalonen - 我知道,这就是为什么我说“看起来像你试图...“,强调”尝试“。 –

+0

没有尝试做单身。我只是试图通过提供工厂方法而不是直接创建对象来允许编码实现,因此允许开发人员编写代码来自我对象 – Igorek