2010-06-10 227 views
6

试图找出如何最好地处理以下情形:依赖注入和工厂

假设一个RequestContext类具有依赖于外部服务,如:

public class RequestContext : IRequestContext 
{ 
    private readonly ServiceFactory<IWeatherService> _weatherService; 

    public RequestContext(ServiceFactory<IWeatherService> weatherService, UserLocation location, string query) 
    { 
     _weatherService = weatherService; 
     ... 

什么样的依赖我是否应该在课堂上要求最终实例化RequestContext?这可能是ServiceFactory<IWeatherService>,但看起来不正确,或者我可以创建沿线的为它的IRequestContextFactory

public class RequestContextFactory : IRequestContextFactory 
{ 
    private readonly ServiceFactory<IWeatherService> _weatherService; 

    public RequestContextFactory(ServiceFactory<IWeatherService> weatherService) 
    { 
     _weatherService = weatherService; 
    } 

    public RequestContext Create(UserLocation location, string query) 
    { 
     return new RequestContext(_weatherService, location, query); 
    } 
} 

然后通过构造函数注入传递IRequestContextFactory

这似乎是一个很好的方法,但这种方法的问题是,我认为它阻碍了可发现性(开发人员必须了解工厂并实施它,这并不是很明显)。

我错过了更好/更容易发现的方式吗?

回答

5

松散耦合的美妙之处在于我们可以不断地隐藏以前的细节

从IRequestContext的使用者的角度来看,RequestContext及其依赖关系的存在纯粹是实现细节。因为Liskov Substitution Principle,消费者只能对付IRequestContext:

public class MyClass 
{ 
    private readonly IRequestContext reqCtx; 

    public MyClass(IRequestContext reqCtx) 
    { 
     if (reqCtx == null) 
     { 
      throw new ArgumentNullException("reqCtx"); 
     } 

     this.reqCtx = reqCtx; 
    } 

    // Implement using this.reqCtx... 
} 

只有在应用程序的Composition Root你需要最后线都在一起。下面是一个穷人的DI方法的草图:

ServiceFactory<IWeatherService> weatherService = 
    new ServiceFactory<IWeatherService>(); 
UserLocation location = new UserLocation; 
string query = "foo"; 

IRequestContext reqCtx = new RequestContext(weatherService, location, query); 

var mc = new MyClass(reqCtx); 
+0

有趣的是,我没有想过直接注入RequestContext,因为它的参数在每个页面请求(ASP.NET MVC)上都会有所不同。使用NInject通过查看查询字符串来正确地为我实例化类是否是一个好主意?或者我会配置NInject使用返回实例的工厂,但在基本级别只需要注入RequestContext? – andreialecu 2010-06-10 13:11:49

+0

我还不知道Ninject已经足够回答关于这个问题的细节了,但是如果它不直接支持这个,你可以使用注入到更高级别消费者的抽象工厂自己实现这个小部分。 – 2010-06-10 13:22:33

0

工厂模式是一个众所周知的,记录和使用的方法。 如果您担心其他开发者无法达到正常速度,请在代码的(xml)文档中输入wikipedia's factory pattern page的链接。

此外,请确保您的工厂名称很清晰 - 微软似乎很喜欢Provider后缀。

+0

“Provider”后缀为+1。需要重构我的工厂。 :)'提供者'为 – andreialecu 2010-06-10 13:17:58

+1

-1。你知道_why_他们是后缀'提供者'吗?不要盲目采用它,只是因为MS使用它。它可能是由于完全不同的原因。 – 2010-06-10 22:59:15

+4

http://msdn.microsoft.com/en-us/library/ms972319.aspx表明它们使用Provider来指示扩展使用ASP.NET提供程序模型的ProviderBase的类。只有在这种情况下,提供者后缀才是适当的。 – 2010-06-10 23:47:42