来自服务层的SimpleInjector请求作用域

本文关键字:SimpleInjector 请求 作用域 服务 | 更新日期: 2023-09-27 18:12:17

我有一个多层应用程序,我的DbContextUnitOfWork的实现位于我的服务层中。该层没有对System.Web的引用。

连同实现一起,还有我的CompositionRoot类,它是从我的UI层引用的,使用扩展来初始化我的所有注入。

但是我的DbContextUnitOfWork需要一个请求范围,我不能像下面的示例那样设置它,因为我没有访问HttpContextWebRequestLifestyle的权限。

为了使用请求范围,我应该将这个RegisterEntityFramework(...)扩展移到我的UI层,还是应该在我的服务层中引用System.Web?还是其他方法

我是依赖注入的新手,所以也许我只是对这种情况下的最佳实践过于偏执。

ServiceLayer/EntityFramework/ComponentRoot.cs

public static class CompositionRoot
{
    public static void RegisterEntityFramework(this Container container)
    {
        var lifestyle = Lifestyle.CreateHybrid(
            lifestyleSelector: () => HttpContext.Current != null, // HttpContext not available
            trueLifestyle: new WebRequestLifestyle(),
            falseLifestyle: new LifetimeScopeLifestyle()
        );
        var contextRegistration = lifestyle.CreateRegistration<EntityDbContext, EntityDbContext>(container);
        container.AddRegistration(typeof(EntityDbContext), contextRegistration);
        container.AddRegistration(typeof(IUnitOfWork), contextRegistration);
    }
}

UILayer/App_Start/ComponentsRoot.cs

public static class RootComposition
{
    public static void Configure()
    {
        var container = new Container();
        container.RegisterEntityFramework(); // extension
        container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
        container.RegisterMvcAttributeFilterProvider();
        container.Verify();
        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
        GlobalConfiguration.Configuration.DependencyResolver = new WebApiDependencyResolver(container);
    }
}

来自服务层的SimpleInjector请求作用域

组合根是应用程序启动路径的一部分。在您的情况下,这是您的web应用程序。组合根引用系统中的所有程序集。将特定于业务层的注册移出此部分的唯一原因是当业务层被多个最终应用程序(例如MVC应用程序和WCF web服务(重用时。

如果你把所有东西都转移到你的网络应用程序中,你的DbContext的注册将很简单:

var scopedLifestyle = new WebRequestLifestyle();
var contextRegistration =
    scopedLifestyle.CreateRegistration<EntityDbContext, EntityDbContext>(container);
container.AddRegistration(typeof(EntityDbContext), contextRegistration);
container.AddRegistration(typeof(IUnitOfWork), contextRegistration);

如果您有多个应用程序,并且需要重用业务层的注册逻辑,那么您不知道该使用什么样的生活方式。在这种情况下,您可以使用ScopedLifestyle:提供业务层组合根

public static void RegisterEntityFramework(this Container container, 
    ScopedLifestyle lifestyle)
{
    var contextRegistration =
        lifestyle.CreateRegistration<EntityDbContext, EntityDbContext>(container);
    container.AddRegistration(typeof(EntityDbContext), contextRegistration);
    container.AddRegistration(typeof(IUnitOfWork), contextRegistration);
}

您可以在Application_Start中调用它,如下所示:

container.RegisterEntityFramework(new WebRequestLifestyle());