2012-12-06 8 views
6

외부 플러그인을 지원하는 ASP.NET MVC 프로젝트에서 작업 중입니다. 이제 Unity에서 Autofac으로 이동하고 플러그인의 평생 객체를 래핑해야합니다. 그것을 참조, Unity에서 나는 이것을 할 수 있습니다.Autofac 평생 관리

public sealed class UnityScopeFactory : IDependencyScopeFactory 
{ 
    private HttpRequestScope _httpRequest; 

    private SingletonScope _singleton; 

    private TransientScope _transient; 

    public IDependencyScope HttpRequest() 
    { 
     return _httpRequest ?? (_httpRequest = new HttpRequestScope()); 
    } 

    public IDependencyScope Singleton() 
    { 
     return _singleton ?? (_singleton = new SingletonScope()); 
    } 

    public IDependencyScope Transient() 
    { 
     return _transient ?? (_transient = new TransientScope()); 
    } 

    private class HttpRequestScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new HttpPerRequestLifetimeManager(); 
     } 
    } 

    private class SingletonScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new ContainerControlledLifetimeManager(); 
     } 
    } 

    private class TransientScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new TransientLifetimeManager(); 
     } 
    } 
} 

나는 Autofac에서 비슷한 일을했지만 나는 내가 (불행히도) 내부에 Autofac의 RegistrationBuilder로 보면서 나는이 함께했다, 그렇게하는 올바른 방법인지 모르겠어요.

public class AutofacScopeFactory : IDependencyScopeFactory 
{ 
    private HttpRequestScope _httpRequest; 

    private SingletonScope _singleton; 

    private TransientScope _transient; 

    public IDependencyScope HttpRequest() 
    { 
     return _httpRequest ?? (_httpRequest = new HttpRequestScope()); 
    } 

    public IDependencyScope Singleton() 
    { 
     return _singleton ?? (_singleton = new SingletonScope()); 
    } 

    public IDependencyScope Transient() 
    { 
     return _transient ?? (_transient = new TransientScope()); 
    } 

    private class HttpRequestScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new CurrentScopeLifetime(); 
     } 
    } 

    private class SingletonScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new RootScopeLifetime(); 
     } 
    } 

    private class TransientScope : IDependencyScope 
    { 
     public object CreateScope() 
     { 
      return new CurrentScopeLifetime(); 
     } 
    } 
} 

또한이 작업을 완료 한 후 어떻게 ContainerBuilder에 전달할 수 있습니까?

Unity에서 나는 이와 같이 할 수 있습니다.

어떻게 IComponentLifetime의 인스턴스를 메서드 체인에 전달합니까? 막 다른 골목입니까?

public class AutofacContainer : IDependencyContainer 
{ 
    private static readonly ContainerBuilder Builder; 

    static AutofacContainer() 
    { 
     Builder = new ContainerBuilder(); 
    } 

    public void RegisterType<TContract, TImplementation>(IDependencyScope scope) where TImplementation : TContract 
    { 
     IComponentLifetime manager = scope.CreateScope() as IComponentLifetime; 

     if (manager != null) 
     { 
      Builder.RegisterType<TImplementation>().As<TContract>(); 
     } 
    } 
} 

답변

9

는 Autofac 그래서 당신이 둥근 구멍에 사각형 고리를 끼려고 할 수도, 범위에게 당신이 설명이 상당히 방법을 구분하지 않습니다.

자동 범위 범위는보다 계층 적입니다. 평생 범위는 자식 과도 범위를 생성 할 수 있습니다. 예를 들어, 당신은 ... 볼 수 있습니다 컨테이너/루트 수명

  • HttpRequest를 범위
    • 작은 작업 별 과도 범위

  • 당신 범위를 "태그 지정"하고 구성 요소를 sp에 등록 할 수 있습니다. ecific named/tagged scope - HttpRequest 범위가 작동하는 방식입니다. 특별한 식별자로 "태깅"됩니다.

    개체를 확인할 때 어떤 수명 범위가 개체를 소유하는지 결정할 때입니다. 해결은 가장 중첩 된 범위에서 발생합니다. 위의 계층 구조에서는 항목이 싱글 톤이든 범위가 요청 되든 관계없이 작은 작업 관련 임시 범위에서 문제를 해결합니다. 싱글 톤이 해결되면 평생 범위 스택을 검색하여 개체의 "소유권"을 루트 수명 범위에 자동으로 할당합니다. 요청 당 항목이 해석되면 특수 "HTTP 요청"식별자를 사용하여 수명 범위에 대한 스택을 검색하고 거기에 소유권을 할당합니다. 공장 범위 항목은 현재 수명 범위에서 해결됩니다.

    참고 :이 토론은 작동 원리가 지나치게 단순화되어 있습니다.There is documentation explaining the lifetime scope mechanism on the Autofac site.

    요점은, 위의 디자인에서 실제로 Autofac이 수행하는 방식에 "신경을 쓰지 않는"몇 가지 사항이 있음을 알 수 있습니다.

    DependencyScopeFactory는 자체 임시 또는 HttpRequest 범위를 만들 수 없습니다. HttpRequest 범위를 시작하고 끝내는 특정 수명 관리 구성 요소가 있으므로이를 사용해야합니다. '글로벌'임시 범위가 없으므로 실제로는 만들 수 없습니다.

    HttpRequest를 범위, 그에 사용이 인라인 있어야하기 때문에 과도 범위에 대한 아날로그가 없습니다

    public ILifetimeScope HttpRequestScope 
    { 
        get { return AutofacDependencyResolver.Current.RequestLifetime; } 
    } 
    

    ... 같은 더 많은 봐, 당신은 MVC를 사용하는 것입니다 가정 :

    using(var transientScope = parentScope.BeginLifetimeScope()) 
    { 
        // Do stuff and resolve dependencies using the transient scope. 
        // The IDisposable pattern here is important so transient 
        // dependencies will be properly disposed at the end of the scope. 
    } 
    

    구성 요소를 등록 할 때 "평생 범위"에 등록하지 마십시오. 실제로는 구성 요소를 구성 요소 레지스트리에 등록하고 구성 요소 등록의 일부에는 구성 요소의 수명이 다 된 후에 소유권 정보가 포함됩니다. 당신은 컨테이너/등록 불가지론 인터페이스를 만들려고 노력하는 경우

    var builder = new ContainerBuilder(); 
    
    // This component is factory-scoped and will be "owned" by whatever 
    // lifetime scope resolves it. You can resolve multiple of these 
    // in a single scope: 
    builder.RegisterType<FirstComponent>().As<ISomeInterface>(); 
    
    // This component is a singleton inside any given lifetime scope, 
    // but if you have a hierarchy of scopes, you'll get one in each 
    // level of the hierarchy. 
    builder.RegisterType<SecondComponent>().InstancePerLifetimeScope(); 
    
    // This component will be a singleton inside a specifically named 
    // lifetime scope. If you try to resolve it in a scope without that 
    // name, it'll search up the scope stack until it finds the scope 
    // with the right name. If no matching scope is found - exception. 
    builder.RegisterType<ThirdComponent>().InstancePerMatchingLifetimeScope("scopename"); 
    
    // This is a per-HTTP-request component. It's just like the 
    // above InstancePerMatchingLifetimeScope, but it has a special 
    // tag that the web integration knows about. 
    builder.RegisterType<FourthComponent>().InstancePerHttpRequest(); 
    

    , 그것은 "평생 범위 매니저"를 필요가 없을 것 - 대신, 당신이 의도 한 평생 범위를 나타내는 몇 가지 매개 변수를 전달해야 할 것 들어오는 매개 변수에 따라 위의 적절한 등록 구문을 수행하십시오.

    다시, I'd recommend you check out that documentation. 또한

    , 유니티를 사용하는 경우는, Autofac (즉 EntLib이 일을 좋아하는 방법이기 때문에) 당신이 유니티 스타일 Autofac을 구성 할 수 있습니다 엔터프라이즈 라이브러리 구성 기 패키지을 가지고있다. 그게 뭔가 체크 아웃 할 수 있습니다.

    Unity 구문을 전혀 사용할 필요가없는 경우 ... 기본 Autofac 방식으로 이동하는 것이 좋습니다. 하나의 컨테이너를 다른 컨테이너처럼 보이게 만들고 행동하게 만드는 것은 꽤 힘든 일입니다.

    플러그인이 별도의 어셈블리 또는 다른 어셈블리에 있다고 가정하면 Autofac 모듈과 함께 멋진 어셈블리 스캔 구문을 쉽게 활용하고 플러그인을 연결할 수 있습니다.

+0

와우! 시간을내어 주셔서 대단히 감사합니다. 정말로 감사드립니다. 정말 PITA가이 단계에서 바뀌 었습니다. 저는 Autofac으로 바꾸고 그것을 시도하고 싶습니다.하지만 다르게 작동하기 때문에 사용할 수 없다면 다른 컨테이너를 사용해야하거나 비용이 그대로 유지되어야합니다. 그것을 atm 변경하기에는 너무 좋습니다. –

+0

좋은 설명 +1! –