C# 工厂类-使用IOC容器注册和解析类型
我不太清楚如何实现这个,或者最好的策略是什么,基本上我有一个(MVC)控制器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
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容器实际上只是一种仪式。所以如果你的场景是兼容的