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

C# 工厂类-使用IOC容器注册和解析类型,c#,asp.net-mvc-3,dependency-injection,inversion-of-control,factory-pattern,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(IService

我不太清楚如何实现这个,或者最好的策略是什么,基本上我有一个(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>();
}
专用iSeries 1\u服务1;
公共测试控制器(IServiceFactory服务工厂)
{
//这也可以从单独的操作调用,
//所以我们只有在需要的时候才能得到它
_service1=serviceFactory.Get();
}
现在我的服务工厂实现有点垃圾,基本上我只有一个字典,可以缓存所有注册的服务和类型:

/// <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;
    }
}
//
///服务工厂级
/// 
/// 
///在应用程序的生存期内,只应创建此类的一个实例
/// 
公共类服务工厂:IServiceFactory
{
/// 
///锁定对象
/// 
私有静态只读对象_lock=new object();
/// 
///映射集合
/// 
私有IDictionary_映射;
/// 
///默认构造函数
/// 
公共服务工厂()
{
_映射=新字典();
注册表映射();
}
/// 
///从工厂得到服务
/// 
public T GetService(),其中T:IService
{
如果(_mappings.Count==0)
抛出新的InvalidOperationException(“没有映射”);
锁
{
var typeName=typeof(T).Name;
if(_mappings.ContainsKey(typeName))
返回(T)_映射[typeName]();
返回默认值(T);
}
}
/// 
///注册此服务工厂所需的映射
/// 
私有无效注册表文件()
{
寄存器(()=>newservice1())
.register(()=>newservice2())
.
.
.register(()=>newservicen());
}
/// 
///注册服务类
/// 
专用ServiceFactory寄存器(Func映射),其中T:IService
{
var type=typeof(T).名称;
if(!\u mappings.ContainsKey(类型))
_添加(类型,映射);
归还这个;
}
}
我的问题是,我可以在服务工厂中使用IOC容器,让它处理类型的注册和解析吗??这是一个好方法吗

或者我会有一个更基本的问题,我是否需要一个服务工厂,我是否应该使用一个

我的MVC控制器需要重构只是一个简单的问题,也就是说,我可以尝试为每个服务使用一个控制器

我只是想知道这里最好的方法是什么,对于DI/工厂模式/其他模式等,我还是个新手:)


非常感谢。

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

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

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


从务实的角度讲,这两种解决方案都很好。但是,使用第二种方法会有更大的风险,因为不清楚在哪里使用哪些服务。

我认为一般的建议是,您应该尝试遵守单一责任原则,在你的情况下,这可以解释为保持你的控制器相对较小,并专注于他们所做的事情。这样,服务依赖项的数量将很小,传递所有必需的服务应该不会造成麻烦

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

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


从务实的角度讲,这两种解决方案都很好。但是,使用第二种方法对代码进行垃圾处理的风险更大,因为不清楚在何处使用了哪些服务。

看起来您正在尝试构建自己的IoC容器。在使用IoC容器时,您不需要工厂。将依赖项注入视为“将依赖项传递到类构造函数”可能会有所帮助。如果您这样想,所有这些可能会变得更清楚。对于这个简单的机制来说,IoC容器实际上只是一种仪式。所以如果你的场景是兼容的