0

지금까지 응용 프로그램의 서비스에 대해 InstancePerRequest()을 지정한 Autofac 구성 클래스를 사용하는 ASP.NET 웹 응용 프로그램이 있습니다.다중 프로젝트 솔루션을위한 자동 범위 구성

그 이후로 자동화 된 작업 프로세스를 실행하는 동일한 솔루션에서 새로운 콘솔 응용 프로그램을 만들었습니다. 콘솔 응용 프로그램에 InstancePerRequest 구성을 사용할 수 없기 때문에 구성을 변경해야합니다. 이상적으로, 모든 구성을 복사하여 내 JobRunner 응용 프로그램에 붙여 넣고 여기에 'InstancePerLifetimeScope()'구성을 사용하고 싶지는 않습니다.

두 프로젝트를 제공하기 위해 동일한 구성을 주로 사용할 수있는 더 나은 솔루션이 있습니까? 아마도 Job Runner 응용 프로그램의 구성을 무시할 수 있지만 모든 단일 서비스의 범위를 변경하지 않아도되는 방법이 있습니까?

+0

작업 주자에게 범위가 필요합니까? – john

+0

잘 모르겠습니다. 이 애플리케이션에서 작업을 실행할 때마다 내 서비스를 해결하고 작업 완료시 종료 할 수 있기를 원합니다. 필자의 어려움은 내 웹 응용 프로그램뿐만 아니라 직업 주자를 모두 충족하도록 구성을 설정하는 방법을 아는 것입니다. –

+3

'InstancePerLequest()'는'InstancePerRequest()'만이 특정 수명 범위이고, 평생 범위가 없으면 루트 범위를 사용해야하기 때문에'InstancePerLifetimeScope()'만으로도 충분할 것입니다. – john

답변

2

InstancePerLifetimeScopeInstancePerRequest은 종종 동일한 바 이얼이지만 분명히 다른 의도가 있습니다. 의도하지 않은 부작용을 쉽게 생성하기 때문에 드롭 인 대체품으로 InstancePerLifetimeScope을 사용하지 않는 것이 좋습니다. 예를 들어, 웹 요청 기간 동안 만 살고 자했던 서비스가있는 경우 (갑자기 루트 범위에서 해결 되었기 때문에) 응용 프로그램이 실행되는 동안 갑자기 수명이 다합니다.

이 효과는 작업 주자 내에서 더 나빠질 수 있습니다. 특히 자신의 수명 범위를 만들지 않는 경우 - 은 모두 하나의 작업이 인스턴스를 공유 함을 의미합니다. 그것에 의존하는 모든 다른 직업을 가진 서비스.

실제로 InstancePerRequest()InstancePerMatchingLifetimeScope()에 잘 대표 된 수명 범위 태그 (MatchingScopeLifetimeTags.RequestLifetimeScopeTag에서 얻을 수 있음)를 위임합니다. 예를 들어, 평생 범위 태그를 생성자 매개 변수로 사용하도록 Autofac 모듈을 변경할 수 있습니다.

internal class MyModule : Module 
{ 
    private string _lifetimeScopeTag; 

    public MyModule(string lifetimeScopeTag) 
    { 
     _lifetimeScopeTag = lifetimeScopeTag; 
    } 

    protected override void Load(ContainerBuilder builder) 
    { 
     builder.RegisterAssemblyTypes() 
      // equivalent to: .InstancePerRequest() 
      .InstancePerMatchingLifetimeScope(_lifetimeScopeTag); 
    }  
} 
평생 함께, 당신은 지금이 동작을 모방 할 수, 작업 러너를 들어

internal static class WebIoC 
{ 
    public static IContainer BuildContainer() 
    { 
     var lifetimeScopeTag = MatchingScopeLifetimeTags.RequestLifetimeScopeTag; 

     var builder = new ContainerBuilder(); 
     builder.RegisterModule(new MyModule(lifetimeScopeTag)); 

     return builder.Build(); 
    } 
} 

: 웹에서 컨테이너를 구축 할 때

지금, 당신은 잘 알려진 수명 범위 태그를 제공해야 너 자신의 범위 태그!

internal static class JobRunnerIoC 
{  
    public const string LifetimeScopeTag = "I_Love_Lamp"; 

    public static IContainer BuildContainer() 
    { 
     var builder = new ContainerBuilder(); 
     builder.RegisterModule(new MyModule(LifetimeScopeTag)); 

     // Don't forget to register your jobs! 
     builder.RegisterType<SomeJob>().AsSelf().As<IJob>(); 
     builder.RegisterType<SomeOtherJob>().AsSelf().As<IJob>(); 

     return builder.Build(); 
    } 
} 

(내가 여기 당신의 작업의 각 인터페이스를 구현 있으리라 믿고있어,의 그것과 같다 가정 해 봅시다) :

public interface IJob 
{ 
    Task Run(); 
} 

지금 당신은 그냥 자신의 평생 범위에서 작업을 실행해야 예 :

public class JobRunner 
{ 
    public static void Main(string[] args) 
    { 
     var container = JobRunnerIoC.BuildContainer(); 

     // Find out all types that are registered as an IJob 
     var jobTypes = container.ComponentRegistry.Registrations 
      .Where(registration => typeof(IJob).IsAssignableFrom(registration.Activator.LimitType)) 
      .Select(registration => registration.Activator.LimitType) 
      .ToArray(); 

     // Run each job in its own lifetime scope 
     var jobTasks = jobTypes 
      .Select(async jobType => 
      { 
       using (var scope = container.BeginLifetimeScope(JobRunnerIoC.LifetimeScopeTag)) 
       { 
        var job = scope.Resolve(jobType) as IJob; 
        await job.Run(); 
       } 
      }); 

     await Task.WhenAll(jobTasks); 
    } 
} 
+0

고맙습니다.현재 모든 유형은 각각에 대해 지정된 범위로 개별적으로 등록됩니다 (예 : "builder.RegistertType () .As () .InstancePerLifetimeScope"). "builder.RegisterAssemblyTypes(). InstancePerMatchingLifetimeScope (lifetimeScope)"라고하면 각 유형 등록에 대한 범위를 지정하지 않아도됩니까? –

+1

예; * 모든 * 어셈블리 유형도 등록됩니다. 일반적으로 컨테이너에 원하는 유형 만 등록하도록 필터링합니다. 'builder.RegisterAssemblyTypes(). (type => typeof (IJob) .IsAssignableFrom (type)). 인스턴스 InstancePerMatchingLifetimeScope (lifetimeScope)'와 같은 것입니다. – gerrod