5

내 Asp.Net MVC3 프로젝트를 변경하여 Autofac을 사용하여 컨트롤러에 서비스를 주입하는 중입니다. 지금까지 이것은 매우 직설적이었습니다. 내 서비스에는 모두 생성자를 통해 주입하는 Telerik OpenAccess db 속성이 있습니다 (서비스 기본 클래스에서). 그리고 내 컨트롤러에는 모두 주입되는 서비스에 대한 생성자 속성이 있습니다.Autofac 속성 주입

public class AuditInfo 
{  
    public string RemoteAddress { get; set; } 

    public string XForwardedFor { get; set; } 

    public Guid UserId { get; set; } 

    public string UserName { get; set; } 
} 

내 서비스 클래스에서 내 OpenAccess를 DB를 속성으로 사용하기 위해 그것을 주입이 클래스의 인스턴스를 가질 필요가 :

나는 컨트롤러의 감사 속성을 캡슐화 AuditInfo라는 클래스를 가지고 다양한 데이터베이스 호출에서 정보를 감사합니다.

문제는 OnActionExecuting의 초기 단계에서 RemoteAddress와 XForwardedFor 중 두 가지 속성 (즉, Request 변수가있는 경우)이 채워지기 때문에 Application_Start에서 인스턴스화 할 수있는 클래스가 아니라는 점입니다.

그러므로, 나는 그런 나의 BaseController 클래스의 OnActionExecuting 방법이 인스턴스화 :

protected override void OnActionExecuting(ActionExecutingContext filterContext) 
{ 
    base.OnActionExecuting(filterContext); 
    db.AuditInfo = AuditInfo;          
} 

public AuditInfo AuditInfo 
{ 
    get 
    { 
     return new AuditInfo() 
     { 
      RemoteAddress = this.Request.ServerVariables["REMOTE_ADDR"], 
      XForwardedFor = this.Request.ServerVariables["X_FORWARDED_FOR"], 
      UserId = this.UserId, 
      UserName = this.UserName 
     }; 
    } 
} 

그래서 - 내 문제/질문은 다음과 같습니다

  1. 내가이 직접 범위를 좋아하지 않는다 OnActionExecuting의 OpenAccess db 속성에 추가합니다.
  2. 기본적으로이 AuditInfo를 임의의 AuditInfo 속성에 삽입해야합니다.
  3. 서비스가 db - controllers에 종속되어 있기 때문에 AuditInfo에 대해 생성자 삽입을 사용할 수 있다고 생각하지 않습니다. - db는 AuditInfo에 의존하지만 AuditInfo는 컨트롤러가 인스턴스화되어 첫 번째 요청을받을 때까지 사용할 수 없습니다. => 순환 의존성 ...

AuditInfo를 등록 정보로 갖는 모든 클래스에 Autofac을 주입하도록 설정하려면 어떻게해야합니까? 아니면 순환 종속성을 피하고 λ/lazy 생성자 속성의 일부 형식을 사용하는 더 좋은 방법이 있습니까?

많은 요청이 같은 세션에 속할 수 있고 다른 IP 주소/사용자 정보가 없더라도 AuditInfo가 모든 요청에 ​​대해 잠재적으로 불필요하게 다시 초기화된다는 점은 전혀 다른가요?

감사

+0

- 스티븐 지적대로'HttpContext.Current'를 사용할 수 있습니다. 그래서'AuditInfo'는 컨트롤러에 의존하지 않으므로 순환 의존성이 없으므로 원하는 경우 생성자 - 주입 'AuditInfo'를 생성 할 수 있습니다. –

+0

글쎄 - 제안 된 솔루션은 요청 개체가 자연스럽게 존재하는 컨트롤러 내부의 AuditInfo 개체를 초기화하는 대신 전역 정적 변수를 사용하여 Request 개체를 참조하기 때문입니다. 나는 서버 변수가 Application_Start에 아직 존재하지 않는다고 생각한다. Application_Start는 th injection이 발생하는 곳이다. 왜냐하면 조치가 먼저 호출되어야하기 때문이다. – t316

답변

2

그것은 Autofac's MVC Integration can resolve an HttpRequestBase for you로 밝혀졌습니다. 따라서 HttpContext.Current.Request을 직접 참조 할 필요가 없습니다.

Autofac의 구현 uses HttpContext.Current 뒤에서 이것은 MVC 프레임 워크가 코드 (또는 Autofac 's)가 실행되기 전에 HttpContext.Current을 설정하기 때문에 가능합니다.따라서 순환 종속성은 없습니다. 컨트롤러에있는 것과 마찬가지로 "자연스럽게 존재"하는 요청이 HttpContext.Current.Request에 있습니다. 스티븐 대신 당신이 정적 변수를 참조하지에 대한 더 나은 느낌을 경우 HttpContext.Current를 사용하는 생성자에 HttpRequestBase을 요구하지만 알 수 있듯이

그래서 당신이 IAuditInfoFactory을 할 수있는 (This question는 가지 방법을 설명합니다).

또한, 더 순환 종속성이 없습니다 당신이 원하는 경우에 당신은 AuditInfo을 생성자 주입 수 : 나는 문제/질문 3에 동의

builder.Register(c => c.Resolve<IAuditInfoFactory>().CreateNew()) 
    .As<AuditInfo>() 
    .InstancePerHttpRequest(); 
+0

스티븐은 정답의 기초를 세우는 데 큰 도움이되었지만 HttpRequestBase 주입이 부족하고 default.kramer가 그 점을 추가함으로써 그의 대답이 좀 더 완성되었습니다. 확실하지 않은 -이 상황에서 정답의 공평한 표시를 처리하기 위해 내가 어떻게 고소 당하고 있는지 알려주세요. 알려 주시기 바랍니다. 지금은 default.kramer의 대답을 올바른 것으로 표시합니다. 감사 – t316

2

대답입니다 : 공장을 사용합니다.

을 필요로하는 유형 내로 IAuditInfoFactory을 주입하고,이 같은 구현을 작성합니다 다음과 같이 해당 클래스를 등록 할 수 있습니다

public class HttpRequestAuditInfoFactory : IAuditInfoFactory 
{ 
    // Service for requesting information about the current user. 
    private readonly ICurrentUserServices user; 

    public HttpRequestAuditInfoFactory(ICurrentUserServices user) 
    { 
     this.user = user; 
    } 

    AuditInfo IAuditInfoFactory.CreateNew() 
    { 
     var req = HttpContext.Current.Request; 

     return new AuditInfo() 
     { 
      RemoteAddress = req.ServerVariables["REMOTE_ADDR"], 
      XForwardedFor = req.ServerVariables["X_FORWARDED_FOR"], 
      UserId = this.user.UserId, 
      UserName = this.user.UserName 
     }; 
    } 
} 

을 :

지금
builder.RegisterType<HttpRequestAuditInfoFactory>() 
    .As<IAuditInfoFactory>() 
    .SingleInstance(); 

당신은 삽입 할 수

+0

빠른 응답을 보내 주셔서 감사합니다. 이것은 제대로 작동하지만 실제로이 솔루션은 HttpContext.Current.Request를 참조하고 HttpContext.Current.Request의 자연적 수명주기 동안 필요한 변수를 저장하고 그 변수를 안으로 삽입하는 대신 외부 컨텍스트에서 변수를 읽는 것에 의존하지 않습니다 느슨한 결합을 가진 외래 환경? 의미 - IAuditInfoFactory 구현체는 System.Web을 참조하고 이것이 작동하기 위해서는 HttpContext.Current.Request에 대해 직접 알아야합니다 ... – t316

+0

이 'HttpRequestAuditInfoFactory' 구현체는 실제로'HttpContext'에 대한 의존성이 강합니다. 그 의미에서 그것은 플랫폼을 인식합니다. 문제가되지는 않지만 그 이유 때문에 응용 프로그램의 일부는 아니지만 [Composition Root] (http://blog.ploeh.dk/2011/)의 일부 여야합니다. 07/28/CompositionRoot.aspx) (CR). 이것은 응용 프로그램의 시작 경로입니다. CR보다 다른 부분은이 'HttpRequestAuditInfoFactory'의 존재를 인식하고 있어야합니다. 응용 프로그램은'IAuditInfoFactory'에 대해서만 알고 있습니다. – Steven

+0

나머지 응용 프로그램은'IAuditInfoFactory'에 대해 알고 있지만 HttpRequestAuditInfoFactory에 대해서는 알지 못하기 때문에 응용 프로그램 (일부)을 Windows 서비스 (예 : Windows 서비스)로 쉽게 마이그레이션 할 수 있습니다. 'IAuditInfoFactory'에 대한 윈도우 서비스 전용 구현이 필요하며 Windows 서비스의 CR ('main' 메소드)에있는'HttpRequestAuditInfoFactory' 대신 연결하십시오. – Steven