web-dev-qa-db-ja.com

単一のブランチの依存関係を取り除くにはどうすればよいですか?

私は3つのプロジェクトに分割されたAPIソリューションに取り組んでいます。

  • API
  • ドメイン
  • DataAccessLayer

DomainプロジェクトICustomerRepositoryに、1つのメソッドでインターフェイスを作成しました。

Domain.Customer GetCustomerById(int customerId)

-

DataAccessLayerは、FooCustomerRepositoryを使用してこのインターフェイスを実装します。

Fooは、アプリケーション固有のDBプロバイダーです。 DataAccessLayerプロジェクトで参照される.NETアセンブリを提供します。

-

APIコントローラーは、Unityを介して注入されるインターフェースのみを使用します。

ApiController.cs

 public class ApiController : Controller
 {
    public ApiController(
         Domain.ICustomerRepository customerRepository)
    {
         ...
    }
}

UnityConfig.cs

public static void RegisterTypes(IUnityContainer container)
{
    container.RegisterType<Domain.ICustomerRepository, DataAccessLayer.FooCustomerRepository>();
}

これを機能させるには、APIプロジェクトでDataAccessLayerへの依存関係、つまりFooアセンブリへの依存関係を作成する必要があります。

-

私はこのプロジェクトに取り組むインターンを割り当てられました。赤テープの理由で、彼のコンピュータにFooをインストールすることはしばらくできませんが、APIプロジェクトに取り組み、コンパイルできるようにしたいと思っています。

ダミーデータを返す偽のリポジトリがAPIプロジェクトで利用可能です。

これをどのように達成できますか?

私は新しいブランチを作成し、UnityConfigや参照を含むDataAccessLayerに関連するすべてを削除することを考えましたが、マージするのは悪夢のように思えます(想像できるように、実際のプロジェクトはもう少しです)繁雑)。

それが唯一の方法ですか?

1
Maxime Visconte

おそらく、通常の方法と開発の両方を処理するための最も信頼できる方法です。それは構成を利用することです。 Net Core/Standardの組み込み 構成API を使用すると、環境固有の構成を標準構成とマージできます。

var environment = Environment.GetEnvironmentVariable("Environment");
var builder = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true)
    .AddEnvironmentVariables();
var config = builder.Build();

そして、値を取得するには:

var dataAccessOptions = config.GetSection("My App");
 // Get value as string
string dataAccessType = dataAccessOptions.Items["DataAccess"];

// Get value as type, can convert enums
var dataAccess = dataAccessOptions.GetValue<DataAccessType>("DataAccess");

設定値を読み取ったら、RegisterTypesメソッドにifステートメントを挿入できます。これにより、デフォルトのFoo DataAccessを条件付きでオーバーライドできます。

public static void RegisterTypes(IUnityContainer container)
{
    if(DataAccess == DataAccessType.Foo)
    {
        container.RegisterType<Domain.ICustomerRepository, 
            DataAccessLayer.FooCustomerRepository>();
    }
    else
    {
        container.RegisterType<Domain.ICustomerRepository, 
            DataAccessLayer.MockCustomerRepository>();
    }
}

このアプローチにより、さらに多くのオプションが利用できるようになります。たとえば、テスト用にモックを挿入する機能など。構成可能なオプションを、実際には制御できないものに制限するだけです。これにより複雑さが増しますが、一般的な意味で問題を解決しながら、このような理想的ではない状況をサポートすることができます。


リフレクションを使用した代替:

public static void RegisterTypes(IUnityContainer container)
{
    var typeName = (DataAccess == DataAccessType.Foo)
        ? "DataAccessLayer.FooCustomerRepository"
        : "DataAccessLayer.MockCustomerRepository";

    var repositoryType = Type.GetType(typeName);

    container.RegisterType(
        typeof(Domain.ICustomerRepository),
        repositoryType);
}

これは、Fooに直接依存しないようにする必要がある場合に必要になることがあります。それは本当にあなたのプロジェクトがどのように設定されているかに依存します。ここでの前提は、Unityがプロジェクトディレクトリまたはプラグインディレクトリのすべてのアセンブリをロードして、実行時にFoo依存関係を見つけることです。

1
Berin Loritsch