2015-01-08 4 views
4

다음과 같은 문제점이 있습니다.IEventProcessor (Event Hub)를 구현하는 클래스에 종속성을 전달하는 방법

우리는 이벤트 허브를 사용합니다. 다음 클래스에서 우리는 IEventProcessor에서 상속받습니다. 그리고 우리가 볼 수있는 것처럼 Service Locator를 사용합니다. 생성자/속성 주입과 함께 작동시킬 수는 없습니다. Castle Windsor는 IEventProcessor에서 상속하는 클래스를 만들 때 종속성을 해결할 수없는 것으로 보입니다. 그게 알려진 이슈입니까, 아니면 제대로 작동시키기 위해해야 ​​할 일이 있습니까?

public class EventProcessor : IEventProcessor 
{ 
    private readonly IEventService _eventService; 
    private readonly ILogger _logger; 
    private readonly Lazy<RetryPolicy> _retryPolicy; 
    private readonly IConfigurationProvider _configurationProvider; 

    public EventProcessor() 
    { 
     try 
     { 
      _eventService = ContainerProvider.Current.Container.Resolve<IEventService>(); 
      _logger = ContainerProvider.Current.Container.Resolve<ILogger>(); 
      _configurationProvider =  ContainerProvider.Current.Container.Resolve<IConfigurationProvider>(); 

     } 
     catch (Exception exception) 
     { 
      _logger.WriteError(string.Format("Error occured when intializing EventProcessor: '{0}'", exception)); 
     } 
    } 

    public Task OpenAsync(PartitionContext context) 
    { 
     return Task.FromResult(0); 
    } 

    public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> events) 
    { 
     var eventsList = events.ToList(); 
     EventData lastEvent = null; 
     foreach (var eventData in eventsList) 
     { 
      _logger.WriteVerbose(string.Format("Consumming {0} events...", eventsList.Count())); 
      _eventService.ProcessEvent(eventData); 
      lastEvent = eventData; 
     } 

     if (lastEvent != null) 
     { 
      await AzureServiceBusRetryPolicy.ExecuteAsync(async() => await context.CheckpointAsync(lastEvent)); 
     } 
    } 

    public async Task CloseAsync(PartitionContext context, CloseReason reason) 
    { 
     _logger.WriteInfo("EventHub processor was closed for this reason: " + reason); 

     if (reason == CloseReason.Shutdown) 
     { 
      await AzureServiceBusRetryPolicy.ExecuteAsync(async() => await context.CheckpointAsync()); 
     } 

    } 


} 

감사

답변

0

이 성 윈저를 사용하여 dependecies을 주입하는 방법이 아니다 : 아래

는 코드입니다. 귀하의 코드 ctor-inject 주어진 매개 변수로 종속성을 나열 생성자와 함께 작동합니다. 당신의 경우에, 이것은 sth처럼 보일 것입니다. like

public EventProcessor(IEventService eventService, ILogger logger, IConfigurationProvider configProvider) 
{ 
    try 
    { 
     this._eventService = eventService; 
     this._logger = logger; // however, i suggest using Property injection for that, see next example 
     this._configurationProvider = configProvider; 

    } 
    catch (Exception exception) 
    { 
     this._logger.WriteError(string.Format("Error occured when intializing EventProcessor: '{0}'", exception)); 
    } 
} 

그러면 EventProcessor 자체를 해결할 수 있으며 이러한 종속성이 주입 될 수 있습니다.

속성 주입는 공개 속성과 함께 작동합니다. 당신은 단순히 그것들을 nomal property처럼 정의하고 그들은 indepentendly 주입됩니다.

public ILogger Logger {get; set;} 

로거를 주입 성 Windsors 방법을 사용하는 것이 좋습니다 (LoggingFacility in Winsdor docs를 참조 아마, 당신이 NLog이나 나 같은 log4net() 사용하려면 -.?> 후 즉시 사용 nugetpackage는 (성 Windor의 log4net가 integraton).

4

내가 Autofac를 사용하지만 같은 문제로 실행하고 있습니다.

나는 IEventProcessorFactory을 구현하고 EventProcessorHost에 프로세서를 등록 할 때 그것을 사용하여 해결했다.

은 전자를 부여하려면 xample, 내 EventProcessorHost 다음과 같은 :

public class EventHubProcessorHost 
{ 
    private readonly IEventProcessorFactory _eventProcessorFactory; 
    private readonly string _serviceBusConnectionString; 
    private readonly string _storageConnectionString; 
    private readonly string _eventHubName; 

    public EventHubProcessorHost(IEventProcessorFactory eventProcessorFactory, string serviceBusConnectionString, string storageConnectionString, string eventHubName) 
    { 
     _eventProcessorFactory = eventProcessorFactory; 
     _serviceBusConnectionString = serviceBusConnectionString; 
     _storageConnectionString = storageConnectionString; 
     _eventHubName = eventHubName; 
    } 

    public void Start() 
    { 
     var builder = new ServiceBusConnectionStringBuilder(_serviceBusConnectionString) 
     { 
      TransportType = TransportType.Amqp 
     }; 

     var client = EventHubClient.CreateFromConnectionString(builder.ToString(), _eventHubName); 

     try 
     { 
      var eventProcessorHost = new EventProcessorHost("singleworker", 
       client.Path, client.GetDefaultConsumerGroup().GroupName, builder.ToString(), _storageConnectionString); 

      eventProcessorHost.RegisterEventProcessorFactoryAsync(_eventProcessorFactory); 
     } 
     catch (Exception exp) 
     { 
      Console.WriteLine("Error on send: " + exp.Message); 
     } 
    } 
} 

내가 전달 공장 내 IoC 컨테이너에 대한 참조가 있습니다

public class MyEventProcessorFactory : IEventProcessorFactory 
{ 
    private readonly IComponentContext _componentContext; 

    public MyEventProcessorFactory(IComponentContext componentContext) 
    { 
     _componentContext = componentContext; 
    } 

    public IEventProcessor CreateEventProcessor(PartitionContext context) 
    { 
     return _componentContext.Resolve<IEventProcessor>(); 
    } 
} 

이 내 EventProcessor에서 정상적으로 생성자 주입을 사용할 수를 :

public class MyEventProcessor : IEventProcessor 
{ 
    private IFoo _foo; 

    public MyEventProcessor(IFoo foo) 
    { 
     _foo = foo; 
    } 

    public Task OpenAsync(PartitionContext context) 
    { 
     return Task.FromResult<object>(null); 
    } 

    public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> events) 
    { 
     foreach (var eventData in events) 
     { 
      // Processing code 
     } 

     await context.CheckpointAsync(); 
    } 

    public async Task CloseAsync(PartitionContext context, CloseReason reason) 
    { 
     if (reason == CloseReason.Shutdown) 
     { 
      await context.CheckpointAsync(); 
     } 
    } 
} 

그럼 시작에서 Autofac 컨테이너에 정상처럼 와이어 모든 업 :

builder.RegisterType<Foo>().As<IFoo>() 

builder.RegisterType<MyEventProcessor>().As<IEventProcessor>() 

builder.Register(c => new MyEventProcessorFactory(c.Resolve<IComponentContext>())).As<IEventProcessorFactory>(); 

희망이 도움이됩니다.

+0

IComponentContext를 삽입하거나 Func eventProcessorFactory를 삽입하면 RegisterType ()를 호출 할 수 있습니다. –