2015-01-14 2 views
1

WebApi 통합에 문제가 있음을 발견했습니다.Autofac + WebApi. InstancePerLifetimeScope 종속성의 이중 인스턴스화

샘플 프로젝트 :은 "~/API/값"에 요청을 만들 수 https://github.com/VKrol/WebApplication19

봅니다, Foo 클래스는 클래스 푸 InstancePerLifetimeScope로 등록되었다는 사실에도 불구하고 두 번 인스턴스화되고있다. Application_AcquireRequestState에서 첫 번째 인스턴스를 해결하고 두 번째 인스턴스가 ValuesController 생성자에 삽입되었음을 유의하십시오. 이것이 버그라고 생각합니다.

감사합니다.

답변

3

짧은 버전입니다 : 당신은 웹 API 프로젝트에있어하지만 당신은 MVC 종속성 해결 프로그램을 사용하려는. 데모 프로젝트에서 MVC 종속성 해결 프로그램을 설정하지 않았습니다.

이벤트 핸들러에서 DependencyResolver.Current.GetService<Foo>();을 호출하면 이 아닌 기본값 인 MVAC 의존성 해결 프로그램을 사용하게됩니다.. 당신이 System.Web.Mvc.DependencyResolver.DefaultDependencyResolver가하는 일을 보면

public class WebApiApplication : HttpApplication { 
    protected void Application_Start() { 
    GlobalConfiguration.Configure(WebApiConfig.Register); 

    var builder = new ContainerBuilder(); 
    var config = GlobalConfiguration.Configuration; 
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); 
    builder.RegisterType<Foo>().AsSelf().InstancePerLifetimeScope(); 

    var container = builder.Build(); 
    // Here's where the Web API resolver is set up... 
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container); 
    } 

    protected virtual void Application_AcquireRequestState(object sender, EventArgs e) { 
    // ...but this call is using the MVC dependency resolver! 
    var foo = DependencyResolver.Current.GetService<Foo>(); 
    } 
} 

, 그것은 요청 유형에 Activator.CreateInstance(type) 호출합니다. 이 경우 귀하의 Foo 유형입니다.

So - 종속성 해결 프로그램이 올바르게 설정되지 않았기 때문에 두 가지 인스턴스가 생성됩니다.

MVC 종속성 해결 프로그램을 사용하려면 per the documentation으로 설정하면됩니다. 이것은 컨테이너를 공유하지만 요청 수명 스코프 메커니즘은 공유하지 않습니다. 웹 API 요청이 들어 오면 반드시 MVC와 같은 방식으로 요청 수명 범위를 생성하지 않으므로 요청 별 의존성은 생각대로 작동하지 않습니다. 웹 API 및 that's also in the docs에서 요청 수명을 처리하는 다른 메커니즘이 있습니다.

OWIN이 아닌 웹 API를 사용하는 경우 GlobalConfiguration.Configuration.DependencyResolver을 호출하여 Autofac으로 설정 한 웹 API 종속성 해결 프로그램을 가져올 수 있습니다. 요청 당 범위를 얻을 수는 없지만 요청 별 종속성을 해결할 수도 없습니다. 그러나 수동으로 서비스를 해결해야하는 경우 그렇게 할 수 있습니다.

OWIN 웹 API로 전환하도록 선택하면 전역 구성 또는 글로벌 종속성 확인 프로그램이 없습니다. 그런 다음 요청 메시지에 첨부 된 DependencyScope을 사용하거나 CommonServiceLocator과 같은 메커니즘을 사용해야합니다.

+0

선생님, 나는 다른 질문이 있어야하지만 질문을 제기 할 수 없다는 것을 알고 있습니다. 마음에 들지 않으면 "InstancePerLifetimeScope"를 도메인 이벤트 핸들러의 범위로 사용해야하는 이유를 말해주십시오. 해당 범위의 작업 코드가 있지만 수명 시간 범위 해결자를 사용하지 않고 범위를 벗어나는 conteiner를 직접 확인하면 추상 추상 구성 요소를 찾을 수 없습니다. 나는 정말로 혼란스럽고 왜 궁금해하니? 내가 서비스를 체크 아웃 할 때, 거기에 여전히 구체적인 구성 요소가 서비스에 있지만 내가 말했듯이 캔트는 거기에서 그것을 검색합니다. –

0

나는 이것이 Autofac의 버그라고 생각하지 않습니다.

LifeTimeScopes are dependant on the scope in which they were resolved. 귀하의 경우, 나는 두 가지 다른 범위에서 Foo을 해결하고 있다고 생각합니다. 응용 프로그램 루트 범위 (Application_AcquireRequestState) 및 하위 범위 (ValuesController) Autofac은 하위 범위의 확인을 허용하지 않으므로 두 가지 서비스 요청이 모두 독립적으로 해결됩니다.

AcquireRequestState에서 해상도를 주석 후, 나는 Foo에 대한 요청 프로젝트에 다른 클래스 NClass을 추가하고 난 Foo 한 번만 예상대로 해결됩니다 것을 알 수있다.

public class ValuesController : ApiController { 
    private readonly Foo _foo; 
    private NClass _nclass; 

    public ValuesController(Foo foo,NClass nClass) { 
     _foo = foo; 
     _nclass = nClass; 
    } 

    public IEnumerable<string> Get() { 
     return new[] { _foo.Id.ToString(), _nclass.Id.ToString()}; 
    } 
} 
public class NClass 
{ 
    private Foo _foo; 
    public NClass(Foo foo) { _foo = foo; } 
    public int Id { get { return _foo.Id; } set { } } 
} 
+0

고맙습니다. 그러나 MVC 컨트롤러의 경우 Foo의 인스턴스가 하나만 생성되는 이유는 무엇입니까? –

+0

MVC 컨트롤러의 스코프가 동일하므로 InstancePerLifeTimeScope가 적용됩니다. – su8898

+0

MVC 및 WebApi 컨트롤러의 Application_AcquireRequestState 범위가 다른 이유는 무엇입니까? –