1

저는 웹 응용 프로그램에서 IoC를 구현하는 세부 사항을 통해 Microsoft.Practices.ServiceLocation을 활용하는 방식으로 작업 해 왔습니다. 나는 특별히 Autofac과 asp.net 통합을 사용하고 있지만, 나는 다른 컨테이너를 열어두고 싶었다. this question 줄을 따라, 나는 웹 애플 리케이션 코드에서 컨테이너에 액세스하는 방법에 대해 우려했다.Autofac, ASP.NET 및 Microsoft.Practices.ServiceLocation

해결할 인터페이스를 주로 정의하는 '핵심'라이브러리가 있습니다. 이 핵심 라이브러리는 내 웹 앱과 다른 앱에서도 사용됩니다. 공통 인터페이스를 정의하는 것이 매우 편리합니다. 나는 이것이 IoC 컨테이너에 접근 할 수있는 훌륭한 장소라고 생각했고, 나는 정적 클래스를 사용했다. 그 속임수는 컨테이너를 정적 클래스에 주입하는 것입니다.

컨테이너가 요청마다 다를 수 있기 때문에 웹 환경에서는 까다로운 반면 웹 이외의 앱에서는 항상 같은 시간대로 표시됩니다. 처음에는 메소드로 컨테이너 direclty를 주입하려고했지만 다음 웹 요청에서 신속하게 실패했습니다! 그래서 나는이 함께했다 :

내 global.asax.cs에서 지금
public static class IoCContainer 
{ 
    public static void SetServiceLocator(Func<IServiceLocator> getLocator) 
    { 
     m_GetLocator = getLocator; 
    } 
    static private Func<IServiceLocator> m_GetLocator = null; 

    public static T GetInstance<T>(string typeName) 
    { 
     return m_GetLocator().GetInstance<T>(typeName); 
    } 
} 

내가 할이 :

protected void Application_Start(object sender, EventArgs e) 
{ 
    var builder = new Autofac.Builder.ContainerBuilder(); 
    ... register stuff ... 
    var container = builder.Build(); 
    _containerProvider = new Autofac.Integration.Web.ContainerProvider(container); 
    Xyz.Core.IoCContainer.SetServiceLocator(() => 
     new AutofacContrib.CommonServiceLocator.AutofacServiceLocator 
      (_containerProvider.RequestContainer)); 
} 
public IContainerProvider ContainerProvider 
{ 
    get { return _containerProvider; } 
} 
static IContainerProvider _containerProvider; 

그리고이 의존성이

var someService = Xyz.Core.GetInstance<ISomeService>(); 

처럼 그래서보다는 해결하기 위해 호출 특정 컨테이너 전달하기 컨테이너를 얻는 방법을 알고있는 델리게이트를 전달합니다. 웹 이외의 응용 프로그램의 경우 delegate는 아마도 builder.Build()가 제공하는 것을 반환 할 것입니다.

제 질문은 전문가의 의견입니다. 나는 컨테이너 제품이 무엇인지 또는 컨테이너 자체가 어디에서 오는 것인지 알지 못해도 종속성을 해결할 수있는 쉬운 방법을 제공합니다. 어떻게 생각해?

답변

2

우리는 IoC가 비 -DI 아키텍처에 도입되었다는 사실 때문에 비슷한 패턴을 사용합니다. 따라서 컨테이너를 명시 적으로 호출하여 서비스를 얻는 것이 필요합니다. 이는 기본적으로 팩토리 패턴입니다.

모든 종속성을 주입 할 수 있고 코드가 더 이상 서비스 로케이터에 종속되지 않을 때 IoC의 진정한 이점이 달성됩니다. Autofac.Integration.Web에는 정적 객체 로케이터를 쓸모없는 페이지 객체에 삽입하는 핸들러가 있습니다. 이 방법이 선호되는 방법이지만, 우리의 경우에도 서비스 위치 지정자는 항상 피할 수는 없습니다.

그렇다면 이미 IoCContainer 클래스를 사용하여 컨테이너에서 앱을 분리 했으므로 IoCContainer 내에서 AutofacServiceLocator를 추가로 추상화 할 필요는 없습니다. 결론적으로 IoCContainer는 이미 서비스 위치 지정자이며 컨테이너 구현에 대한 직접 액세스를 "허용"해야합니다.

public static class IoCContainer 
{ 
    private static IContext GetContainer() 
    { 
     var cpa = 
      (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance; 
     return cpa.ContainerProvider.RequestContainer; 
    } 

    public static T GetInstance<T>() 
    { 
     return GetContainer().Resolve<T>(); 
    } 
} 
+0

이 베드로 매우 멋지다하지만 난 아마 심지어 웹 기반, 다른 상황에서 내 '.Core'라이브러리를 재사용 할 수 있기를 기대했다 : 여기

은 서비스 로케이터 클래스에 내 걸릴 것입니다 . 아직도 너무 많은 추상화를 피하는 데 도움이되기 때문에 이것이 훌륭한 대답이라고 생각합니다. 감사! – n8wrl

+0

당신의 요점을 봅니다. 여전히 서비스 로케이터 패턴을 완전히 없애고 의존성 주입 만 사용하면이 문제를 전혀 해결할 필요가 없습니다. –