使用Autofac进行会话服务唯一ID初始化

时间:2013-08-07 07:05:53

标签: c# .net windows-services ioc-container autofac

我有一个Windows服务项目,我使用Autofac作为IOC容器。此服务从交换服务器“嗅探”邮件,因此每次在Exchange服务器上发生某些事件时,我的Windows服务都会检查是否应将该新项目复制到交换服务器以外的其他位置。

对于每一个happing事件(邮件发送,邮件收发,新任务等),我希望有一个唯一的会话ID,我可以用它来记录。然后,更容易在日志中跟踪Exchange服务器事件(使用NLog)。

我尝试了以下但是我每次都会得到一个新的指南。我想每个会话/交换服务器事件只需要一个新的guid:

在我的autofac设置类(bootstrapper.cs)

builder.RegisterType<SessionService>().As<ISessionService>()
    .InstancePerLifetimeScope();

我也试过这个,但结果相同:

builder.RegisterType<SessionService>().As<ISessionService>()

我的会话服务实施:

public class SessionService : ISessionService
{
    private readonly Guid _sessionGuid;

    public SessionService()
    {
        _sessionGuid = Guid.NewGuid();
    }

    public Guid GetNewSessionGuid()
    {
        return _sessionGuid;
    }
}

然后,例如,当尝试将信息从Exchange服务器事件保存到其他系统时,我必须记录一些内容。可能只是信息或它可能是错误,无论哪种方式它应该是相同的guid事件。

因此,例如在我的PushNotificationListener类中,我使用Property injection:

public ILogger Logger
{
    get
    {
        using (var scope = IocContainer.Container.BeginLifetimeScope())
        {
            return scope.Resolve<ILogger>();
        }
    }
}

public ILogFormater LogFormater
{
    get
    {
        using (var scope = IocContainer.Container.BeginLifetimeScope())
        {
            return scope.Resolve<ILogFormater>();
        }
    }
}

public ISessionService SessionService
{
    get
    {
        using (var scope = IocContainer.Container.BeginLifetimeScope())
        {
            return IocContainer.Container.Resolve<ISessionService>();
        }
    }
}

然后我像这样调用guid的会话服务:

Logger.LogInfo(LogFormater.EventLogFormat(
    SessionService.GetNewSessionGuid(),
    exchangeEventType.ToString(),
    message.Notification.ItemsElementName[count].ToString(),
    _service.ImpersonatedUserId.Id,
    mailEvent.TimeStamp));

在我的MailService类中,我首先拥有构造函数,因此您可以看到依赖注入:

public MailService(
    ILogger logger,
    ILogFormater logFormater,
    ISessionService sessionService)
{
    _logger = logger;
    _logFormater = logFormater;
    _sessionService = sessionService;
}

当例如新邮件已保存在另一个系统中时,我调用会话guid:

_logger.LogInfo(_sessionService.GetNewSessionGuid().ToString());

对PushNotificationListener类和MailService类中的_sessionService.GetNewSessionGuid()方法的调用给了我两个不同的guid。

我希望他们是同一个guid。我该怎么做?

1 个答案:

答案 0 :(得分:0)

问题是由PushNotificationListener类中的属性引起的。由于您在其中创建了新的生命周期范围,因此将在该范围内创建新的SessionService。防止这样做。

相反,每个会话应该只有一个生命周期范围。您应该在引发事件之后和解析根对象之前直接创建新的生命周期范围(并且只能创建一个生命周期范围)。从那时起,应使用构造函数注入注入所有依赖项。这确保了在该范围内,只有一个SessionService