「作成に費用がかかり、使用される可能性がある」に関連する同様のケースがあり、独自の IoC 実装で、ファクトリ サービスの自動サポートを追加しています。
基本的に、これの代わりに:
public SomeService(ICDBurner burner)
{
}
あなたはこれをするでしょう:
public SomeService(IServiceFactory<ICDBurner> burnerFactory)
{
}
ICDBurner burner = burnerFactory.Create();
これには 2 つの利点があります。
- バックグラウンドで、サービスを解決したサービス コンテナーは、要求された場合にバーナーを解決するためにも使用されます。
- これにより、サービス コンテナー自体をパラメーターとしてサービスに挿入するのが一般的な方法である、この種のケースで以前に見た懸念が軽減されます。どちらか教えて」
ファクトリ オブジェクトは比較的簡単に作成でき、多くの問題を解決します。
これが私のファクトリークラスです:
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 が実装されます。上記のサービスは、ポリシーを指定する 1 つのパラメーター (ポリシーが使用されていない場合は 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 バーナー サービスを解決する方法を知っているサービス、ファクトリ サービスを使用できるようになりました。これは、次の理由で役立ちます。
- 同時に複数のサービスを解決したい場合があります (2 枚のディスクを同時に書き込みますか?)。
- 必要ない場合もあれば、作成にコストがかかる場合もあるため、必要な場合にのみ解決します
- 既存のサービス インスタンスをクリーンアップすることを期待/試行する代わりに、解決、破棄、解決、破棄を複数回行う必要がある場合があります。
- また、コンストラクターで、必要なサービスと必要な可能性があるサービスにフラグを立てています
以下は同時に2つです。
using (var service1 = container.Resolve<ISomeService>())
using (var service2 = container.Resolve<ISomeService>())
{
service1.Instance.DoSomethingHere();
service2.Instance.DoSomethingHere();
}
同じサービスを再利用するのではなく、次の 2 つの例を次に示します。
using (var service = container.Resolve<ISomeService>())
{
service.Instance.DoSomethingHere();
}
using (var service = container.Resolve<ISomeService>())
{
service.Instance.DoSomethingElseHere();
}