Sea*_*son 4 c# autofac asp.net-web-api
我让AutoFac与MVC4一起正常工作.我正在尝试过渡到Web API 2.这是我设置AutoFac的原因:
public class AutofacRegistrations
{
public static void RegisterAndSetResolver()
{
// Create the container builder.
var containerBuilder = new ContainerBuilder();
// Register the Web API controllers.
containerBuilder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Only generate one SessionFactory ever because it is expensive.
containerBuilder.Register(x => new NHibernateConfiguration().Configure().BuildSessionFactory()).SingleInstance();
// Everything else wants an instance of Session per HTTP request, so indicate that:
containerBuilder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).InstancePerApiRequest();
containerBuilder.Register(x => LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType)).InstancePerApiRequest();
containerBuilder.RegisterType<NHibernateDaoFactory>().As<IDaoFactory>().InstancePerApiRequest();
containerBuilder.RegisterType<StreamusManagerFactory>().As<IManagerFactory>().InstancePerApiRequest();
// Build the container.
ILifetimeScope container = containerBuilder.Build();
// Create the depenedency resolver.
var dependencyResolver = new AutofacWebApiDependencyResolver(container);
// Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver;
}
}
Run Code Online (Sandbox Code Playgroud)
我非常有信心所有这一切都是正确的.当我试图设置一些测试用例时,我的问题出现了.我的测试用例的基类不是控制器,因此它不会自动传递任何东西.在MVC4中,我做了以下事情:
[SetUp]
public void SetUp()
{
HttpSimulator = new HttpSimulator().SimulateRequest();
Logger = DependencyResolver.Current.GetService<ILog>();
DaoFactory = DependencyResolver.Current.GetService<IDaoFactory>();
Session = DependencyResolver.Current.GetService<ISession>();
ManagerFactory = DependencyResolver.Current.GetService<IManagerFactory>();
}
[TearDown]
public void TearDown()
{
HttpSimulator.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,WebAPI中没有DependencyResolver.Current.所以我想知道如何正确地做到这一点?
这构建,但不正确.我收到了"会话已关闭!"的消息.当我尝试执行测试用例时:
[SetUp]
public void SetUp()
{
using (var scope = GlobalConfiguration.Configuration.DependencyResolver.BeginScope())
{
// TODO: Consider initializing Helpers during setup to keep this DRY.
Logger = (ILog)scope.GetService(typeof(ILog));
DaoFactory = (IDaoFactory)scope.GetService(typeof(IDaoFactory));
Session = (ISession)scope.GetService(typeof(ISession));
ManagerFactory = (IManagerFactory)scope.GetService(typeof(IManagerFactory));
}
}
Run Code Online (Sandbox Code Playgroud)
使用WebAPI,您不需要访问当前的解析程序,因为当前的依赖项范围通常与入站一起出现HttpRequestMessage.该消息也是负责生成新请求范围的消息.
您可以在System.Net.Http.HttpRequestMessageExtensions.GetDependencyScope方法中查看此代码.
您在WebAPI中会注意到的一件大事是,您实际上并不需要在全局静态值中设置任何内容 - 也就是说,您不需要设置全局配置/解析器,因为现在所有内容都是基于实例的.
对于测试,这意味着:
HttpRequestMessage使用适当的依赖项解析程序和配置创建.HttpRequestMessage掉,这将依次处理依赖范围等.HttpRequestMessage.GetDependencyScope()如果他们需要手动解决某些问题,将使用单独的测试,并且请求消息将用于协调/传递范围.以更具体的方式,它可能看起来像:
private HttpRequestMessage _request;
[SetUp]
public void SetUp()
{
var builder = new ContainerBuilder();
// Register stuff.
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
var config = new HttpConfiguration();
config.DependencyResolver = resolver;
config.EnsureInitialized();
this._request = new HttpRequestMessage();
this._request.SetConfiguration(config);
}
[TearDown]
public void TearDown()
{
this._request.Dispose();
}
[Test]
public void Test()
{
// When you need to resolve something, use the request message
this._request.GetDependencyScope().GetService(typeof(TheThing));
}
Run Code Online (Sandbox Code Playgroud)
这样做的好处在于,您不必在每次测试后都使用全局配置设置或重置静态值.
您可能想知道为什么要传递整个请求消息而不仅仅是依赖解析器 - 原因是请求消息是协调和控制依赖范围的生命周期的原因.否则,当您GetDependencyScope多次调用时,您将获得多个不同的范围,而不是您期望的范围.
从设计角度考虑的一些事项:
RegisterAndSetResolver方法中重复使用它,而不必担心全局静态被篡改.RegisterAndSetResolver您可以考虑仅HttpConfiguration在WebApiConfig.Register WebAPI为您提供的方法中连接的对象上设置解析器,而不是修改全局静态配置.将HttpConfiguration对象作为参数并在其上设置解析器而不是全局.无论如何,HttpRequestMessage是WebAPI的方法.
| 归档时间: |
|
| 查看次数: |
4517 次 |
| 最近记录: |