我有以下问题。
我们使用Event Hub。在下面的类中,我们从IEventProcessor继承,您可以看到我们使用Service Locator。我们无法使用构造函数/属性注入。当目标从IEventProcessor继承的类时,Castle Windsor似乎无法解析依赖关系。这是一个已知的问题还是我需要做些什么才能让它发挥作用?
以下是代码:
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 :(得分:4)
我正在使用Autofac,但遇到了同样的问题。
我通过实施IEventProcessorFactory并在EventProcessorHost中注册处理器时使用它来解决。
举个例子,我的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>();
希望这有帮助。
答案 1 :(得分:0)
这不是使用城堡温莎注入家属的方法。鉴于您的代码 ctor-injection 可以使用构造函数将依赖关系列为参数。在你的情况下,这将看起来......像
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,并注入这些依赖项。
属性注入适用于公共属性。你只需将它们定义为正常属性,它们就会被独立注入。
public ILogger Logger {get; set;}
考虑使用Castle Windsors方式注入记录器(参见LoggingFacility in Winsdor docs。也许,你想使用NLog或log4net(像我一样)? - &gt;然后有一个现成的nugetpackage(Castle Windor) log4net integraton)。