2

私が行っているように依存関係を動的に解決するのは良いことですか?どこでもコンストラクタインジェクションを使用することをお勧めします。私はそれをやっているやり方の欠点を本当に理解していません。以下のようにコードスニペット..Autofacを使用して依存関係を動的に解決する

Employee.cs

public class Employee 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public int Age { get; set; } 
    public Department Department { get; set; } 
} 

IRepository.cs

public interface IRepository<TModel> where TModel : class 
    { 
     void Add(); 
     IEnumerable<TModel> GetAll(); 
     IEnumerable<TModel> GetByID(); 
    } 

Repository.cs

public class Repository<TModel> : IRepository<TModel> where TModel : class 
{ 
    public void Add() 
    { 
     throw new NotImplementedException(); 
    } 

    public IEnumerable<TModel> GetAll() 
    { 
     throw new NotImplementedException(); 
    } 

    public IEnumerable<TModel> GetByID() 
    { 
     throw new NotImplementedException(); 
    } 
} 

EmployeeController.cs Global.asaxの

protected void Application_Start() 
{ 
    GlobalConfiguration.Configure(WebApiConfig.Register); 

    var builder = new ContainerBuilder(); 
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); 

    builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); 

    var container = builder.Build(Autofac.Builder.ContainerBuildOptions.None); 
    var webApiResolver = new AutofacWebApiDependencyResolver(container); 
    GlobalConfiguration.Configuration.DependencyResolver = webApiResolver; 
} 

iが5つのリポジトリをしたと言う

public class HomeController : ApiController 
{ 
    IComponentContext _container; 

    public HomeController(IComponentContext container) 
    { 
     this._container = container; 
    } 

    public Repository<TModel> Using<TModel>() where TModel :class 
    { 
     var repository = _container.Resolve(typeof(IRepository<TModel>)); 
     return repository as Repository<TModel>; 
    } 

    [HttpGet] 
    public IEnumerable<Employee> GetEmployees() 
    { 
     return Using<Employee>().GetAll(); 
    } 
} 

、コンストラクタ・インジェクションは、私が作る要求のためのすべての5つの依存関係を解決します。私はそれぞれのリクエストごとに5つのリポジトリを使用しないかもしれません。だから私はそれをやっているような型を渡すことによって依存関係を動的に解決すると思ったUsing<TModel>()。どんな提案も高く評価されます。ありがとうございました...!!

+1

基本的には、コンテナを直接使用してアンチパターンとみなすサービスロケータパターンを使用しています。詳細はこちら http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/ 私は個人的には、必要なリポジトリだけを注入する複数のコントローラに分割します。だからEmployeeControllerなど。 –

+0

@Praveenに直接 'container'を使わないでください。 'IDependencyResolver.GetService'でIoCコンテナを使って登録された型を解決するだけで十分です。 –

答えて

3

アプリケーションコンポーネントの内部で直接コンテナを使用しないようにします。メンテナンス性やテスト容易性の問題など、あらゆる種類の問題が発生します。アプリケーションコード内からインスタンスを直接解決する方法は、サービスロケータと呼ばれるwell-known anti-patternです。

最初のリファクタリングとして、代わりにUnit of Workパターンを適用できます。作業ユニットは、基礎となるリポジトリへのアクセスを可能にします。例えば:Composition Root以内

public interface IUnitOfWork 
{ 
    IRepository<TModel> Repository<TModel>(); 
} 

public sealed class HomeController : ApiController 
{ 
    private readonly IUnitOfWork _unitOfWork; 

    public HomeController(IUnitOfWork unitOfWork) 
    { 
     this._unitOfWork = unitOfWork; 
    } 

    [HttpGet] 
    public IEnumerable<Employee> GetEmployees() 
    { 
     return this._unitOfWork.Repository<Employee>().GetAll(); 
    } 
} 

it is allowedがコンテナにアクセスする場合)、我々は今、動的リポジトリを解決IUnitOfWork実装を作成することができます

private sealed class AutofacUnitOfWork : IUnitOfWork 
{ 
    private readonly IComponentContext _container; 

    public AutofacUnitOfWork(IComponentContext container) 
    { 
     this._container = container; 
    } 

    public IRepository<TModel> Repository<TModel>() 
    { 
     return _container.Resolve<IRepository<TModel>>(); 
    } 
} 

このパターンは、アプリケーションの大幅コンポーネントおよび防止を簡素化サービスロケータのアンチパターンが典型的に引き起こすのは欠点です。

作業パターンの単位を適用することは、右方向への有用なステップであるかもしれないが、より良いアプローチは、直接作業ユニットをスキップし、単に直接アプリケーションコンポーネントに必要なリポジトリを注入することである。

public sealed class HomeController : ApiController 
{ 
    private readonly IRepository<Employee> _employeeRepository; 

    public HomeController(IRepository<Employee> employeeRepository) 
    { 
     this._employeeRepository = employeeRepository; 
    } 

    [HttpGet] 
    public IEnumerable<Employee> GetEmployees() 
    { 
     return this._employeeRepository.GetAll(); 
    } 
} 

私は5つのリポジトリを持っていると言います。コンストラクタインジェクションは、私が要求する5つの依存関係をすべて解決します。私はそれぞれのリクエストごとに5つのリポジトリを使用しないかもしれません。

パフォーマンスの観点からは、通常、依存関係の使用の有無は関係ありません。ほとんどの場合、Autofacは十分速く、実際には本番システムでパフォーマンス上の問題が発生することはほとんどありません。

しかし、デザインの観点からは、クラスには多くの依存関係がある場合には心配する必要がありますが、メソッドはいくつかの依存関係を使用します。つまり、クラス内のメソッドにはほとんど結束がありません。これは、クラスを複数の小さなクラスに分割する必要があることを示しています。それはmultiple responsibilitiesです。

関連する問題