2016-09-26 2 views
1

ASP.Net WebApi 2 프로젝트의 StartUp 클래스에서 종속성을 해결하려고합니다. Autofac은 종속성 삽입을 구성하는 데 사용됩니다. 시나리오는 다음과 같습니다.StartUp에서 Autofac으로 사용자 별/요청 별 종속성 해결

  • 다른 사용자는 서로 다른 데이터를 볼 수 있습니다. 모든 사용자는 해당 사용자가 특정 데이터를 볼 수있는 특정 권한을가집니다.
  • 여러 경계를 포함하는 도메인 기반 아키텍처가 사용되고 있습니다. 도메인 및 데이터 액세스 계층에서 교차 경계 호출을 수행 할 수 없습니다. 사용자의 허용 된 데이터의 모든 코드를 가져 오기 위해서는 경계 간 통화를해야하기 때문에 중요합니다.
  • 모든 사용자에 대해 허용 된 데이터 만 검색하기 위해 데이터 액세스 계층 내부의 데이터를 필터링하려고합니다. 국경 간 통화는 허용되지 않습니다.
  • 이를 위해 사용자가 볼 수있는 레코드의 모든 코드 목록을 주입하려고합니다.
  • 이 경우 사용자를 기준으로이 목록을 만드는 Autofac이있는 공장을 등록하려고했습니다. 팩토리를 StuffFactory으로, 목록을 StuffModel으로합시다.

이제 모든 문제는 InstancePerRequest으로 등록해야합니다. 이로 인해 InvalidOperatonException이 발생합니다. 이는 StartUp에서 요청한 수명 범위에 액세스 할 수 없기 때문에 합리적입니다.

'AutofacWebRequest'와 일치하는 태그가있는 범위가 인스턴스 요청 범위에서 볼 수 있습니다. 이는 일반적으로 HTTP 별 요청으로 등록 된 구성 요소가 SingleInstance() 구성 요소 (또는 이와 유사한 시나리오)에 의해 요청되었음을 나타냅니다. 웹 통합에서는 항상 DependencyResolver.Current 또는 ILifetimeScopeProvider.RequestLineetime에서 종속성을 요청하고 컨테이너 자체에서는 요청하지 않습니다 .

허용 된 물건이 컨테이너에 등록되어있는 코드는 :

private IContainer RegisterAllowedStuff(IContainer container) 
{ 
    var builder = new ContainerBuilder(); 

    builder.Register(x => GetAllowedStuffForUser(container)) 
     .As<StuffModel>() 
     .InstancePerRequest(); 

    builder.Update(container); 
    return container; 
} 

private static StuffModel GetAllowedStuffForUser(IContainer container) 
{ 
    var stuffFactory = container.Resolve<IStuffFactory>(); 
    return stuffFactory.CreateStuffModel(Helper.GetParsedUserName()); 
} 

나는 가지 여기에서 발전하는 방법에 붙어 있어요. 제가 완전히 감독하고있는 Autofac 문제에 대한 쉬운 해결책이 있습니까? 누군가가 어쩌면 이것을 구현할 수있는 더 좋은 아이디어를 가지고 있습니까? 미리 감사드립니다!

답변

4

시작 클래스에는 비즈니스 논리가 없어야합니다. Autofac을 사용하면 해결 시간에 호출 할 람다 메서드를 등록 할 수 있습니다. 현재 HttpRequest을 사용할 수 있으므로이 람다를 InstancePerRequest으로 등록 할 수 있습니다.귀하의 경우에는

, 당신은 당신이 이런 식으로 할 수있는 StuffModelInstancePerRequest로 등록 할 경우 : 그런데

builder.RegisterType<ConcreteStuffFactory>() 
     .As<IStuffFactory>(); 
builder.Register(c => c.Resolve<IStuffFactory>() 
         .CreateStuffModel(Helper.GetParsedUserName())) 
     .As<IStuffModel>() 
     .InstancePerRequest(); 

는 또한 안티 패턴처럼 보이는 도우미 클래스를 사용하지 않을 것 예를 들어 IUserContextProvider과 같이 현재 사용자의 사용자 이름을 가져 오는 서비스를 만들 수 있습니다. 또한 ConcreteStuffFactory

public class ConcreteStuffFactory 
{ 
    public ConcreteStuffFactory(IUserContextProvider userContextProvider) 
    { 
     this._userContextProvider = userContextProvider; 
    } 

    private readonly IUserContextProvider _userContextProvider; 


    public IStuffModel CreateStuffModel() 
    { 
     String userName = this._userContextProvider.UserName; 
     // do things with userName 
    } 
} 

및 등록에 IUserContextProvider 종속성을 추가 할 수 있습니다

builder.RegisterType<ConcreteStuffFactory>() 
     .As<IStuffFactory>(); 
builder.RegisterType<HttpContextUserContextProvider>() 
     .As<IUserContextProvider>() 
     .InstancePerRequest(); 
builder.Register(c => c.Resolve<IStuffFactory>().CreateStuffModel()) 
     .As<IStuffModel>() 
     .InstancePerRequest(); 
+0

은 내가 이런 간단한 해결책을 내려다 알고 있었다. 감사! 'Helper'에 관해서는 : 완전히 유효한 주석이며 코드베이스의 오래된 부분을 리펙토링했습니다. –

0

제 생각에는 제공된 예외 텍스트가 코드가 실행되지 않는 이유를 정확하게 설명합니다.

내게는 응용 프로그램의 수명 동안 한 번만 호출되는 Startup-method의 요청 별 인스턴스에 액세스 할 수 없다는 것이 매우 당연합니다.

코드를 요청별로 호출 할 수있는 위치로 이동하는 것이 좋습니다. 예를 들어 custom action filter을 작성하는 것에 대해 생각해 봤습니까?