1

これを実装する方法、または最良の戦略が何であるかはよくわかりません。基本的に(MVC)コントローラーを持っています

public TestController(IService1 service1, IService2 service2,...)
{ }

(現時点ではパラメータは 2 つしかありませんが、増加する可能性があります)。

私のアイデアは、サービス ファクトリ クラスを作成するというものでした。そのため、各サービスのパラメータを持つ代わりに、ファクトリ用のパラメータを 1 つ持つことで、必要なサービスを取得できます。

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 コントローラーにリファクタリングが必要なのは単純なことです。つまり、サービスごとに 1 つのコントローラーを試してみることができますか??

ここで最良のアプローチが何であるかについてのヒントが欲しいだけです.DI /ファクトリーパターン/その他のパタ​​ーンなどに関しては、私はまだ新人です:)

どうもありがとう。

4

1 に答える 1

1

一般的なアドバイスは、単一責任の原則に従うべきだということだと思います。これは、あなたの場合、コントローラーを比較的小さく保ち、その役割に集中することと解釈できます。そうすれば、サービスの依存関係の数が少なくなり、必要なすべてのサービスを渡すのが面倒になることはありません。

とはいえ、複数のサービスに 1 つのアクセス ポイントを提供したり、渡されるパラメーターの数を減らしたり、サービス間の相互作用を許可したりすると便利な場合があります (IoC コンテナーは循環関係/依存関係を好みません)。

後者が必要だったので、プロパティを通じてすべてのサービスへのアクセスを提供する UnitOfWork クラスを作成することにしました。UnitOfWork は、すべてのサービスをコンストラクター パラメーターとして受け取り、コンストラクター パラメーターとしてコントローラーに渡します。これにより、チェーン全体 (サービス、uow、およびコントローラー) を構築して IoC 経由で注入できるようになり、(コンストラクターで多くの作業を行わないようにすることで) オブジェクトの構築コストを低く抑えることができれば、パフォーマンスのオーバーヘッドは最小限に抑えられます。

実用的には、どちらのソリューションでも問題ありません。ただし、2 番目の方法では、どのサービスがどこで使用されているかが不明確になるため、コードがスパゲッティ化されるリスクが高くなります。

于 2013-04-10T19:07:31.407 に答える