我有一个与“创建成本高且可能使用”相关的类似案例,在我自己的 IoC 实现中,我正在为工厂服务添加自动支持。
基本上,而不是这样:
public SomeService(ICDBurner burner)
{
}
你会这样做:
public SomeService(IServiceFactory<ICDBurner> burnerFactory)
{
}
ICDBurner burner = burnerFactory.Create();
这有两个优点:
- 在幕后,解析您的服务的服务容器也用于解析刻录机,如果以及何时请求
- 这减轻了我之前在这种情况下看到的担忧,典型的方法是将服务容器本身作为参数注入到您的服务中,基本上是说“该服务需要其他服务,但我不会轻易告诉你哪些”
工厂对象很容易制作,解决了很多问题。
这是我的工厂课程:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LVK.IoC.Interfaces;
using System.Diagnostics;
namespace LVK.IoC
{
/// <summary>
/// This class is used to implement <see cref="IServiceFactory{T}"/> for all
/// services automatically.
/// </summary>
[DebuggerDisplay("AutoServiceFactory (Type={typeof(T)}, Policy={Policy})")]
internal class AutoServiceFactory<T> : ServiceBase, IServiceFactory<T>
{
#region Private Fields
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly String _Policy;
#endregion
#region Construction & Destruction
/// <summary>
/// Initializes a new instance of the <see cref="AutoServiceFactory<T>"/> class.
/// </summary>
/// <param name="serviceContainer">The service container involved.</param>
/// <param name="policy">The policy to use when resolving the service.</param>
/// <exception cref="ArgumentNullException"><paramref name="serviceContainer"/> is <c>null</c>.</exception>
public AutoServiceFactory(IServiceContainer serviceContainer, String policy)
: base(serviceContainer)
{
_Policy = policy;
}
/// <summary>
/// Initializes a new instance of the <see cref="AutoServiceFactory<T>"/> class.
/// </summary>
/// <param name="serviceContainer">The service container involved.</param>
/// <exception cref="ArgumentNullException"><paramref name="serviceContainer"/> is <c>null</c>.</exception>
public AutoServiceFactory(IServiceContainer serviceContainer)
: this(serviceContainer, null)
{
// Do nothing here
}
#endregion
#region Public Properties
/// <summary>
/// Gets the policy that will be used when the service is resolved.
/// </summary>
public String Policy
{
get
{
return _Policy;
}
}
#endregion
#region IServiceFactory<T> Members
/// <summary>
/// Constructs a new service of the correct type and returns it.
/// </summary>
/// <returns>The created service.</returns>
public IService<T> Create()
{
return MyServiceContainer.Resolve<T>(_Policy);
}
#endregion
}
}
基本上,当我从我的服务容器构建器类构建服务容器时,所有服务注册都会自动获得另一个协同服务,为该服务实现 IServiceFactory,除非程序员已经为该服务明确注册了他/她自己。然后使用上述服务,其中一个参数指定策略(如果不使用策略,则可以为 null)。
这允许我这样做:
var builder = new ServiceContainerBuilder();
builder.Register<ISomeService>()
.From.ConcreteType<SomeService>();
using (var container = builder.Build())
{
using (var factory = container.Resolve<IServiceFactory<ISomeService>>())
{
using (var service = factory.Instance.Create())
{
service.Instance.DoSomethingAwesomeHere();
}
}
}
当然,更典型的用途是与您的 CD Burner 对象一起使用。在上面的代码中,我当然会解决服务,但它是对所发生情况的说明。
因此,请使用您的 cd 刻录机服务:
var builder = new ServiceContainerBuilder();
builder.Register<ICDBurner>()
.From.ConcreteType<CDBurner>();
builder.Register<ISomeService>()
.From.ConcreteType<SomeService>(); // constructor used in the top of answer
using (var container = builder.Build())
{
using (var service = container.Resolve<ISomeService>())
{
service.Instance.DoSomethingHere();
}
}
在服务内部,您现在可以拥有一项服务,即工厂服务,它知道如何根据请求解决您的 cd 刻录机服务。这很有用,原因如下:
- 您可能希望同时解决多个服务(同时刻录两张光盘?)
- 您可能不需要它,而且创建它的成本可能很高,因此您仅在需要时才解决它
- 您可能需要多次解决、处置、解决、处置,而不是希望/尝试清理现有服务实例
- 您还在构造函数中标记您需要哪些服务以及您可能需要哪些服务
这里同时有两个:
using (var service1 = container.Resolve<ISomeService>())
using (var service2 = container.Resolve<ISomeService>())
{
service1.Instance.DoSomethingHere();
service2.Instance.DoSomethingHere();
}
这是两个一个接一个,而不是重复使用相同的服务:
using (var service = container.Resolve<ISomeService>())
{
service.Instance.DoSomethingHere();
}
using (var service = container.Resolve<ISomeService>())
{
service.Instance.DoSomethingElseHere();
}