webapi中的autofac注册一些单例组件,每个请求

时间:2018-02-05 14:19:35

标签: autofac autofac-module

我们的框架具有以下结构:

  • webapi项目
  • 基本CQRS项目
  • Nhibnerate配置项目

该解决方案使用Autofac连接所有类。 api将加载所有程序集并注册这些程序集中的所有模块。

大多数模块只是查找所有接口和实现,并且每个请求都使用实例,效果很好。

CQRS是命令和查询处理程序的一个非常基本的示例。由于将来会有很多,并且它们可能有各种依赖关系,我不想手动编写工厂来获取所有处理程序(或者在API中添加对每个处理程序的引用)。

为了解决上述问题,我有一个Command / Query HandlerFactory,它接受它想要运行的命令或查询。使用反射,它为它找到处理程序的类型,并使用基本handlerResolver,以便它可以获得处理程序的新实例。要做到这一点,我将ILifetimeScope传递给解析器,这样只能在一个地方完成。 (我知道引用lifetimescope是一种反模式,但我的感觉是,如果我最终会得到数百个命令和查询,我最终会得到一个可怕的工厂,它会占用所有可能的依赖关系,并使用autofac来实现把它连接起来更干净。)

如果所有内容都作为每个请求的实例保留,则一切正常,所有类都将得到解析,命令和查询将会运行。问题是,对于每个API请求,NHibnernate配置都会重建,在我的机器上需要大约1.5秒。这意味着几乎每个请求都需要2秒才能响应。

我想要做的是能够将NHibnerate配置和sessionFactory注册为单例(因为它不会有任何敏感/用户数据相关信息),因此尽可能少地创建它。同时根据请求离开所有处理程序和其他类,以便它们独立并尽快处理。

连接web api的主要类:

public static class AutoFacSetup
{
    public static IContainer Create()
    {
        var builder = new ContainerBuilder();

        // this is to insist we use hbm config rather than fluent as there are two implentations of IConfigurationFactory
        builder.RegisterType<OurHbmConfigurationFactory>().SingleInstance();

        var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();

        // Register your Web API controllers.
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).InstancePerRequest();
        builder.RegisterAssemblyModules(assemblies);

        builder.RegisterSelf();
        var container = builder.Build();

        return container;
    }

    public static void RegisterSelf(this ContainerBuilder builder)
    {
        IContainer container = null;
        builder.Register(c => container).AsSelf().SingleInstance();
        builder.RegisterBuildCallback(c => container = c);
    }
}

其中一个模块类的示例:

public class AutoFacInstallerModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        var assembly = GetType().Assembly;
        builder
            .RegisterAssemblyTypes(assembly)
            .Except<NhibernateDbConnectionFactory>(x => x.SingleInstance())
            .Except<MySessionFactory>(x => x.SingleInstance())
            .AsImplementedInterfaces()
            .InstancePerRequest();
    }
}

0 个答案:

没有答案