工厂类 - 使用IOC容器注册和解析类型

时间:2013-04-10 18:15:28

标签: c# asp.net-mvc-3 dependency-injection inversion-of-control factory-pattern

我不太确定如何实现这个,或者最好的策略是什么,基本上我有一个(MVC)控制器

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 /工厂模式/其他模式等方面,我仍然是新手:)

非常感谢。

1 个答案:

答案 0 :(得分:1)

我认为一般的建议是你应该坚持单一责任原则,在你的情况下可以解释为保持你的控制器相对较小并专注于他们的工作。这样,服务依赖的数量就会很少,并且传递所有必需的服务不应该是一件麻烦。

也就是说,有时为多个服务提供单个访问点,减少传递的参数数量,或允许服务本身之间的交互(IoC容器不喜欢循环关系/依赖关系)会很有用)。

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

务实地说,两种解决方案都没问题。但是,使用第二种方法对代码进行破坏的风险更大,因为不清楚在哪里使用哪些服务。