1

我不太清楚如何实现这一点,还是最好的策略是什么,基本上我有一个(MVC)控制器工厂类 - 使用IoC容器来注册和解析类型

public TestController(IService1 service1, IService2 service2,...) 
{ } 

(在时刻只有2个参数,但可能会增加)。

我的想法是,我会创建一个服务工厂类,因此不是每个服务的参数,我们可以代替有一个工厂,然后得到什么服务,我们需要

private IService1 _service1; 
public TestController(IServiceFactory serviceFactory) 
{ 
    // this could also be called from a separate action, 
    // so we only get it when we need it 
    _service1 = serviceFactory.Get<IService1>(); 
} 

现在我的服务工厂实现是有点废话,只是有本质上我是缓存所有注册服务的字典和类型:

/// <summary> 
/// Service factory class 
/// </summary> 
/// <remarks> 
/// Only one instance of this class should be created during the lifetime of the application 
/// </remarks> 
public class ServiceFactory : IServiceFactory 
{ 
    /// <summary> 
    /// Locking object 
    /// </summary> 
    private static readonly object _lock = new object(); 

    /// <summary> 
    /// Collection of mappings 
    /// </summary> 
    private IDictionary<string, Func<IService>> _mappings; 

    /// <summary> 
    /// Default constructor 
    /// </summary> 
    public ServiceFactory() 
    { 
     _mappings = new Dictionary<string, Func<IService>>(); 
     registerMappings(); 
    } 

    /// <summary> 
    /// Get a service from the factory 
    /// </summary> 
    public T GetService<T>() where T : IService 
    { 
     if (_mappings.Count == 0) 
      throw new InvalidOperationException("There are no mappings"); 

     lock (_lock) 
     { 
      var typeName = typeof(T).Name; 
      if (_mappings.ContainsKey(typeName)) 
       return (T)_mappings[typeName](); 

      return default(T); 
     } 
    } 

    /// <summary> 
    /// Register the mappings needed for this service factory 
    /// </summary> 
    private void registerMappings() 
    { 
     register<IService1>(() => new Service1()) 
      .register<IService2>(() => new Service2()) 
      . 
      . 
      .register<IServiceN>(() => new ServiceN()); 
    } 

    /// <summary> 
    /// Register the service classes 
    /// </summary> 
    private ServiceFactory register<T>(Func<IService> mapping) where T : IService 
    { 
     var type = typeof(T).Name; 
     if (!_mappings.ContainsKey(type)) 
      _mappings.Add(type, mapping); 

     return this; 
    } 
} 

我的问题是,我可以在维修厂使用IoC容器,让它处理注册和类型的解决?这是一个好方法吗?

或者我可以有一个更基本的问题,我需要一个服务工厂,我应该使用吗?

这仅仅是因为我的MVC控制器需要重构,即我可以尝试和坚持一个控制器为每个服务一个简单的事情?

只是想在最好的办法是什么在这里的一些技巧,我还是个新人,当谈到DI /工厂模式/一些,其他模式等:)

非常感谢。

+0

看起来你正试图建立自己的IoC容器。使用IoC容器时,您不需要工厂。 – 2013-04-10 18:19:47

+1

将依赖注入想象为*“将依赖关系传递给类构造函数”可能会有帮助。*如果您这么想,那么所有这些都可能变得更加清晰。对于这个简单的机制,IoC容器实际上只是很多仪式。因此,如果你的场景与编写一个以某个接口为参数的类的想法兼容,然后在构建该类时提供了该接口的一些实现,那么它对于IoC来说可能是一个很好的候选者。 – 2013-04-10 18:19:59

+0

我不会在这里添加额外的复杂层。 – 2013-04-10 18:26:15

回答

1

我觉得一般的建议是你应该尽量坚持单一职责原则,而你的情况可以解释为使您的控制器相对较小,集中在他们做什么。这样,服务依赖关系的数量将会很小,并且通过所有必需的服务不应该是一件麻烦事。

也就是说,有时候可以为多个服务提供一个单一的接入点,减少传递的参数数量,或者允许服务之间的交互(IoC容器不喜欢循环关系/依赖)。

我有必要为后者,并决定建立,提供给所有服务槽性质的访问的UnitOfWork类。 UnitOfWork将所有服务作为构造函数参数,并作为构造函数参数传递给控制器​​。这允许通过IoC构造和注入整个链(服务,uow和控制器),并且如果您保持较低的对象构建成本(避免在构造函数中做很多工作),那么性能开销将很小。

从实用的角度来看,两种解决方案都可以。但是,用第二种方法进行代码化的风险更大,因为哪里使用哪种服务尚不清楚。

+0

+1。我绝对同意。 “IServiceFactory”的使用只是闻起来像[Service Locator反模式](http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/),我所有的蜘蛛SOLID-感觉都是叮当作响这里。 OP应该可能将这些相关服务组合在一个[聚合服务](http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/)或者[命令模式](http://www.cuttingedge 。它/博客/史蒂芬/枢轴/ entry.php?ID = 91)。 – Steven 2013-04-10 19:20:57

相关问题