2017-05-17 18 views
0

私はaspコアアプリケーションで一般的なDIの使用法を持っています。aspコアのDIでパラメータを持つオブジェクトを初期化する

public void ConfigureServices(IServiceCollection services) 
{ 
    ... 
    services.AddScoped(typeof(IUnitOfWork), typeof(UnitOfWork));//DAL 
    services.AddScoped(typeof(IUpService), typeof(UpService));//BLL 
    ... 
} 

コントローラDIによりUpServiceを得る:

public BaseController(IUpService upService) 
{ 
    _upService = upService; 
} 

ひいてはBLL(upservice)でインスタンスをUnitOfWorkの取得:ベースコントローラで

public UpService(IUnitOfWork unitOfWork) 
{ 
    _unitOfWork = unitOfWork; 
} 

をiはプロパティあるCurrentUser

public User CurrentUser 
{ 
    get 
    { 
     User user = null; 
     var tokenCookie = HttpContext.Request.Headers.FirstOrDefault(c => c.Key == "token"); 
     if (!string.IsNullOrEmpty(tokenCookie.Value) && tokenCookie.Value != "undefined") 
     { 
      user = _upService.GetUserById(new Guid(tokenCookie.Value)); 
     } 
     return user; 
    } 
} 
を有します

W私が必要とする帽子は、CurrentUserをBL層に(UpServiceへ)渡すことです。 ASPコアのDIでそれを実現するには?

UPD: ここで私は現在のユーザーが必要なUpServiceの部分です。あなたは抽象化へCurrentUserを抽出する必要があり

答えて

1

public class UpService : IUpService 
{ 
    private IUnitOfWork _unitOfWork; 

    public User CurrentUser { get; set; } 


    public UpService(IUnitOfWork unitOfWork, IUserContext userContext) 
    { 
     _unitOfWork = unitOfWork; 
     //CurrentUser = userContext.CurrentUser; 
    } 


    public void Update(Document doc) 
     { 
//here complex BL and then... 
       Document local; 
       var entity = _unitOfWork.DocumentsRepository.GetByID(doc.Id); 
       if (entity != null && HasChanges(local, entity)) 
       { 
        entity.ChangedById = CurrentUser.Id; 
        _unitOfWork.Save(); 
       } 
     } 

     public User GetUserById(Guid id) 
     { 
      return _unitOfWork.UserRepository.GetByID(id); 
     } 

...、のはそれIUserContextを呼びましょう。この抽象化は、コアレイヤーで実装できます。この方法でBLとDALはアクセスできます。 Webアプリケーションの一部として、ASP.NET Coreに適合する実装を作成します。基本的には、CurrentUserプロパティにあるロジックが含まれています。このアダプタは、いつものように登録することができ

public class AspNetUserContextAdapter : IUserContext 
{ 
    private readonly IHttpContextAccessor _accessor; 
    private readonly IUpService _upService; 

    public AspNetUserContextAdapter(IHttpContextAccessor accessor, IUpService _upService) { 
     _accessor = accessor; 
     _upService = upService; 
    } 

    public User CurrentUser 
    { 
     get 
     { 
      var context = _accessor.HttpContext; 
      var tokenCookie = context.Request.Headers.FirstOrDefault(c => c.Key == "token"); 
      return !string.IsNullOrEmpty(tokenCookie.Value) && tokenCookie.Value != "undefined" 
       ? _upService.GetUserById(new Guid(tokenCookie.Value)) 
       : null; 
     } 
    } 
} 

を:たとえば、次のように

public interface IUserContext 
{ 
    User CurrentUser { get; } 
} 

アダプタが見ることができるその上で

services.AddTransient<IUserContext, AspNetUserContextAdapter>(); 

、あなたはASPを登録する必要があります.NETコアのIHttpContextAccessor(旧バージョンのASP.NETコア)ではデフォルトで登録されていないため、

services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
+0

スティーブン、ご返信ありがとうございます。私は必要と思われる。しかし、実現後、「循環依存」が見つかった場合。実際に私はIUpServiceでIUserContextを尋ねます。結果として、IUserContextにはIUpServiceが必要ですが、IUpserviceにはIUserContextが必要です。そしてそれを解決する方法は? –

+0

@VitalyMosin:あなたの質問を更新し、 'UpService'の実装を示してください。しかし、一般的に、循環参照はSingle Responsibility Principle違反によって引き起こされます。言い換えれば、 'UpService'はおそらく大きすぎ、分割する必要があります。 – Steven

+0

私はRSPに違反する可能性があることに同意します。解決策は、userContextのサービスインジェクションをカットし、upserviceだけにトークンを渡すことです。その後、アップサービスコンストラクタでUserを取得し、_upService.CurrentUserプロパティでコントローラに返します。 –

関連する問題