我们的框架具有以下结构:
该解决方案使用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();
}
}