2017-04-20 14 views
4

는 I는 DLL 느릅이 라이브러리 내의DbContext 만들지

public class MyDbContext { 
    [...] 
} 

같은 형식을 노출이 또한

public void RegisterServices(Container container) { 
    container.Register<MyDbContext>(Lifestyle.Scoped); 
} 

이 어셈블리와 같은 용기 내의 MyDbContext를 등록 IPackage 구현을 다음 두 가지 유형의 응용 프로그램에서 참조됩니다. - 웹 API 프로젝트 - asp.net mvc 응용 프로그램

이 웹 API 프로젝트

var container = new Container(); 
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle(); 
InitializeContainer(container); 
container.RegisterWebApiControllers(GlobalConfiguration.Configuration); 
container.Verify(); 

의 초기화 내가합니다 (MVC 응용 프로그램에서)는 수수께끼 큐에서 메시지를받을 때 이것은 MVC 응용 프로그램

var container = new Container(); 
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle(); 
InitializeContainer(container); 
container.RegisterMvcControllers(Assembly.GetExecutingAssembly()); 
container.Verify(); 

의 초기화이다 컨테이너는이

public class MyHandler : BaseMessageHandler, IHandleMessages<MyMessage>, IHandleMessages<IFailed<MyMessage>> 
{ 
    public MyHandler(ILog logger, MyDbContext context) { 
     _logger = logger; 
     _context = context; 
    } 
} 

같은 메시지 처리기를 인스턴스화 할 시도하지만

말하는 오류가 발생

Rebus.Retry.ErrorTracking.InMemErrorTracker - 처리되지 않은 예외 ID의 1 동안 85feff07-01a6-4195-8deb-7c8f1b62ecc3과 메시지 처리 : SimpleInjector.ActivationException을 다음 MyDbContext '는 웹 요청'생활로 등록되지만 인스턴스이다 활성 (웹 요청) 범위의 컨텍스트 외부에서 요청했습니다. 다음 스택 추적

at SimpleInjector.Scope.GetScopelessInstance[TImplementation](ScopedRegistration`1 registration) 
at SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration`1 registration, Scope scope) 
at SimpleInjector.Advanced.Internal.LazyScopedRegistration`1.GetInstance(Scope scope) 
at lambda_method(Closure) 
at SimpleInjector.InstanceProducer.GetInstance() 
at SimpleInjector.Container.GetInstance[TService]() 

나는 또한 MVC 응용 프로그램의 설정에 비동기 범위가 지정된 라이프 스타일을 시도했지만 오류가 실질적으로 동일과

.

답변

3

Rebus는 웹 요청 스레드가 아닌 백그라운드 스레드에서 처리기를 실행합니다. 이는 Rebus 파이프 라인의 일부로 WebRequestLifestyle을 사용할 수 없음을 의미합니다.

처리기를 실행하기 전에 비동기 범위를 명시 적으로 시작해야합니다. 당신은 데코레이터/프록시로 그렇게 할 수 있습니다.

MVC가 AsyncScopedLifestyle 대신 WebRequestLifestyle을 사용하므로 하이브리드 라이프 스타일을 사용해야합니다. 다음과 같이

당신은 당신의 MVC 응용 프로그램에서 하이브리드 라이프 스타일을 적용 할 수

container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
    defaultLifestyle: new AsyncScopedLifestyle(), 
    fallbackLifestyle: new WebRequestLifestyle()); 

으로 보여야 장식은 다음 다음과 같이

public sealed class AsyncScopedMessageHandler<T> : IHandleMessages<T> 
{ 
    private readonly Container container; 
    private readonly Func<IHandleMessages<T>> decorateeFactory; 
    public AsyncScopedMessageHandler(Container container, Func<IHandleMessages<T>> factory) 
    { 
     this.container = container; 
     this.decorateeFactory = factory; 
    } 
    public async Task Handle(T message) { 
     using (AsyncScopedLifestyle.BeginScope(this.container)) { 
      var decoratee = this.decorateeFactory.Invoke(); 
      await decoratee.Handle(message); 
     } 
    } 
} 

당신은 당신의 장식을 등록 할 수 있습니다 :

container.RegisterDecorator(
    typeof(IHandleMessages<>), 
    typeof(AsyncScopedMessageHandler<>), 
    Lifestyle.Singleton); 

이 데코레이터는 MVC와 웹 API 프로젝트 모두에 등록해야합니다. 티.

+0

안녕하세요, 스티븐, 답장을 보내 주셔서 감사합니다.MessageHandler에 어떤 수정을해야하는지 명확히 설명해 주시겠습니까? 사실 저는 단순히 핸들러를'container.Register , MyMessageHandler> (Lifestyle.Transient)'로 등록합니다. 나는 그것을 바꿔야 할까? – Lorenzo

+2

안녕하세요 @ Lorenzo, 귀하의 메시지 처리기 또는 등록을 변경할 필요가 없습니다; 그것은 Rebus가 제공하는 잘 디자인 된 추상화와 결합 된 Simple Injector의 아름다움입니다. 마지막 데코레이터로 데코레이터를 등록하면 (더 많이 가지고 있다면) 그냥 작동하기 시작해야합니다. – Steven

+0

좋은 품질의 대답. 감사합니다! – Lorenzo