【问题标题】:Dependency Injection to Handle Case When HttpContext.Current Doesn't ExistHttpContext.Current 不存在时的依赖注入处理案例
【发布时间】:2013-10-30 20:55:29
【问题描述】:

我有一个 ASP.NET MVC 应用程序,在我的 Application_Start 事件中我有以下代码:

container.RegisterType<ISessionFactory>(new ContainerControlledLifetimeManager(), new InjectionFactory(c => {
    return BuildSessionFactory();
}));
container.RegisterType<ISession>(new PerRequestLifetimeManager<ISession>(), new InjectionFactory(c => {
    return c.Resolve<ISessionFactory>().OpenSession();
}));

会话工厂 (ISessionFactory) 在应用程序的整个过程中都存在。会话 (ISession) 在 ASP.NET 请求期间存在。我还在 Application_EndRequest 事件中处理会话。这使我可以在整个应用程序中注入 ISession,它可以按预期工作。

我现在正在尝试将任务调度构建到我的应用程序中。我在 Application_Start 事件中添加了以下代码:

var timer = new System.Timers.Timer(5000);
timer.Elapsed += (sender, e) => {
    var thread = new Thread(new ThreadStart(() => {
        var service = DependencyResolver.Current.GetService<ISomeService>();

        ...
    }));
    thread.Start();
};
timer.Enabled = true;

这应该每 5 秒运行一次。 ISomeService 的实现在构造函数中注入了 ISession,我不希望更改此类。当它尝试解决 ISession 时出现我的问题,因为它试图在 HttpContext.Current 为空的线程中解决它,因此引发异常。我想知道我应该如何注册会话来处理这种情况。非常感谢您的帮助。

谢谢

这是我的 PerRequestLifetimeManager 类,以防万一:

public class PerRequestLifetimeManager<T> : LifetimeManager {
    public override object GetValue() {
        return HttpContext.Current.Items[typeof(T).AssemblyQualifiedName];
    }

    public override void RemoveValue() {
        HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName);
    }

    public override void SetValue(object newValue) {
        HttpContext.Current.Items[typeof(T).AssemblyQualifiedName] = newValue;
    }
}

【问题讨论】:

    标签: asp.net multithreading nhibernate dependency-injection unity-container


    【解决方案1】:

    解析 ISessionFactory 并自己管理会话的生命周期。

    var timer = new System.Timers.Timer(5000);
    timer.Elapsed += (sender, e) => {
    var thread = new Thread(new ThreadStart(() => {
        var service = DependencyResolver.Current.GetService<ISessionFactory>();
        using(var session = service.OpenSession())
        {
            //do something with session
        }
    
        ...
    }));
    thread.Start();
    };
    timer.Enabled = true;
    

    编辑: Unity 具有多个容器实例的功能,这些实例可以具有不同的配置。这样您就可以为“服务”配置不同的生命周期管理器

    【讨论】:

    • 感谢您的回答。但是,这将需要我更改我无法执行的服务(在给出的示例中为 ISomeService),因为这需要大量重构,并且当我确实希望缓存每个请求的会话时也不起作用。
    • 更新:这实际上是一种享受。我从 PerThreadLifetimeManager 继承了我的 PerRequestLifetimeManager 并在 HttpContext.Current 返回 null 时调用基本方法。这样它就会自动工作。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-06
    • 2017-04-12
    • 2019-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多