1

私のasp.net mvcコントローラーのコンストラクターには、次の方法でデータベースと通信する複数(5)のインターフェイスがあります。

[HttpGet]
public ActionResult Create()
{          
 var releases = _releaseDataProvider.GetReleases();
 var templates = _templateDataProvider.GetTemplates();
 var createTestplanViewModel = new CreateTestplanViewModel(templates, releases);
 return PartialView(createTestplanViewModel);
}

上記では、データベースからデータを取得するために 2 つの異なるインターフェイスを使用しています。

ビジネス ケース: テスト計画を作成するには、利用可能なリリースとユーザーが選択できるテンプレートをユーザーに示す必要があります。

これら 2 つのインターフェイスの依存関係/過剰注入を減らすにはどうすればよいですか

4

3 に答える 3

1

MVC プロジェクトで:

public class MyController : Controller
{
    private readonly IQueryProcessor _queryProcessor;

    public MyController(IQueryProcessor queryProcessor)
    {
        _queryProcessor = queryProcessor;
    }

    [HttpGet]
    public ActionResult Create()
    {
        var releases = _queryProcessor.Execute(new ProvideReleaseData());
        var templates = _queryProcessor.Execute(new ProvideTemplateData());
        var createTestplanViewModel = AutoMapper.Mapper
            .Map<CreateTestplanViewModel>(releases);
        AutoMapper.Mapper.Map(templates, createTestplanViewModel);
        return PartialView(createTestplanViewModel);
    }
}

次に、現在のプロバイダーの実装をコンストラクターで実装に挿入できますIQueryHandlerIQueryProcessor単なるインフラです。詳細については、https ://cuttingedge.it/blogs/steven/pivot/entry.php?id=92 を参照してください。

コメントへの返信:

リンク先のサイトにあります。これが私のものです:

using System.Diagnostics;
using SimpleInjector;

namespace MyApp.Infrastructure
{
    sealed class SimpleQueryProcessor : IQueryProcessor
    {
        private readonly Container _container;

        public SimpleQueryProcessor(Container container)
        {
            _container = container;
        }

        [DebuggerStepThrough]
        public TResult Execute<TResult>(IDefineQuery<TResult> query)
        {
            var handlerType = typeof(IHandleQueries<,>)
                .MakeGenericType(query.GetType(), typeof(TResult));

            dynamic handler = _container.GetInstance(handlerType);

            return handler.Handle((dynamic)query);
        }
    }
}
于 2012-08-04T20:29:17.060 に答える
0

データベースを分離する一般的な方法としては、作業単位を使用する方法があります。asp.netの素晴らしい記事と、 MSDNの別の記事を次に示します。

要約すると、すべてのデータベース/サービス呼び出しが存在し、データベース ロジックを処理できる単一のユニットを作成します。これにより、複数のインターフェイスの依存関係が 1 つのポイントに削減されるため、コントローラーに 1 つのクラスを挿入するだけで済みます。

MSDN の記事からの引用:

Martin Fowler によると、Unit of Work パターンは「ビジネス トランザクションの影響を受けるオブジェクトのリストを維持し、変更の書き込みと同時実行性の問題の解決を調整します」。

于 2012-08-04T19:46:59.747 に答える
0

編集

基本的に、ここでコンストラクターの依存関係の数を減らすためにこれらのオプションがあるようです:

  1. コントローラーを分割する
  2. 2 つのインターフェイスの前にレイヤーを追加します
  3. プロパティインジェクションに切り替える
  4. サービスロケーター

#3 と #4 は適切な測定のために含まれていますが、明らかに実際に依存関係の数を減らすわけではなく、コンストラクターからそれらを隠すだけです。また、いくつかの欠点もあり、ほとんどの場合、サービス ロケーターは特に悪いと考えています。

#1については、コンストラクターが実際に2つ以上のジョブを実行していると感じ、分割できる明確な分離がある場合は、そうします。しかし、あなたの回答から、あなたはすでにこれを検討しており、これをしたくないと思います。

それは#2を残します-別のレイヤーを追加します。この場合、その特定のビュー モデルのファクトリ インターフェイスを導入することになります。単純に、この ICreateTestplanViewModelFactory に名前を付けますが、必要に応じて、アプリにとってより意味のある名前を付けることができます。その上の単一のメソッドは、CreateTestplanViewModel を構築します。

これにより、このビューのデータが 2 つのソースから取得されているという事実は、実装の詳細にすぎません。コンストラクターの依存関係として IReleaseDataProvider と ITemplateDataProvider を取る実装を結び付けます。


これは、私が提案していたことに沿っています。

public interface IProvideTestPlanSetupModel
{
    CreateTestplanViewModel GetModel();
}

public class TestPlanSetupProvider : IProvideTestPlanSetupModel
{
    private readonly IReleaseDataProvider _releaseDataProvider;
    private readonly ITemplateDataProvider _templateDataProvider;

    public TestPlanSetupProvider(IReleaseDataProvider releaseDataProvider, ITemplateDataProvider templateDataProvider)
    {
        _releaseDataProvider = releaseDataProvider;
        _templateDataProvider = templateDataProvider;
    }

    public CreateTestplanViewModel GetModel()
    {
        var releases = _releaseDataProvider.GetReleases();
        var templates = _templateDataProvider.GetTemplates();

        return new CreateTestplanViewModel(releases, templates);
    }
}

public class TestPlanController : Controller
{
    private readonly IProvideTestPlanSetupModel _testPlanSetupProvider;

    public TestPlanController(IProvideTestPlanSetupModel testPlanSetupProvider)
    {
        _testPlanSetupProvider = testPlanSetupProvider;
    }

    [HttpGet]
    public ActionResult Create()
    {
        var createTestplanViewModel = _testPlanSetupProvider.GetModel();
        return PartialView(createTestplanViewModel);
    }
}

コントローラーの外側にビュー モデルを構築したくない場合は、ビュー モデルにコピーするのと同じプロパティを持つ中間オブジェクトをインターフェイスで提供できます。しかし、これはばかげています。このデータの組み合わせは、ビュー モデルが表現するはずの特定のビューにのみ関連するからです。

余談ですが、同じモデルを介して読み取り/書き込みを行うと、かなり一般的な煩わしさに遭遇しているようです。これらの問題が気になるので、CQRS を調査することをお勧めします。これにより、これらのタイプのクエリについてデータベースと直接やり取りすることについての不快感が軽減され、私たちが楽しんでいる階層化の迷路を回避するのに役立つでしょう。有望に思えますが、まだ実稼働アプリケーションでテストする喜びはありませんでした。

于 2012-08-04T19:40:26.250 に答える