C# 如何使用DryIoc解决WebAPI控制器的依赖关系
我一直在阅读文档,对于如何实现这一点,我有点困惑。我有一个名为NewsController的WebAPI控制器,我将在下面列出。它有一个构造函数,当前有三个依赖项。我已经为DryIoc创建了一个静态类,因此我可以在整个项目中全局使用它,并在启动时初始化它 我想做的是在我的DryIoc类中注册控制器及其依赖项,然后在NewsController中以某种方式解决这个问题。我想这样做的原因是,当我开始测试时,我可以让测试项目更改注册控制器的范围,并使用存根或模拟实现 注册依赖性C# 如何使用DryIoc解决WebAPI控制器的依赖关系,c#,unit-testing,asp.net-web-api,inversion-of-control,dryioc,C#,Unit Testing,Asp.net Web Api,Inversion Of Control,Dryioc,我一直在阅读文档,对于如何实现这一点,我有点困惑。我有一个名为NewsController的WebAPI控制器,我将在下面列出。它有一个构造函数,当前有三个依赖项。我已经为DryIoc创建了一个静态类,因此我可以在整个项目中全局使用它,并在启动时初始化它 我想做的是在我的DryIoc类中注册控制器及其依赖项,然后在NewsController中以某种方式解决这个问题。我想这样做的原因是,当我开始测试时,我可以让测试项目更改注册控制器的范围,并使用存根或模拟实现 注册依赖性 public stat
public static class RegisterDependencies
{
public static Container container;
public static void Initialize()
{
container = new Container(rules => rules
.WithDefaultReuseInsteadOfTransient(Reuse.InWebRequest)
.WithoutThrowOnRegisteringDisposableTransient()
.WithoutImplicitCheckForReuseMatchingScope());
container.Register<INewsManager, NewsManager>();
container.Register<IGetNews, NewsManager>();
container.Register<IAddNews, NewsManager>();
container.Register<ILoggingService, Logger>();
container.Register<NewsController>(made: Made.Of(() => new NewsController
(Arg.Of<ILoggingService>(), Arg.Of<IGetNews>(), Arg.Of<IAddNews>(),
Arg.Of<INewsManager>())));
}
}
public static class RegisterDependencies
{
public static IContainer controllerContainer;
public static void InitializeControllerContainer(IContainer ControllerContainer)
{
ControllerContainer.RegisterMany<ILoggingService, Logger>(setup: Setup.With(allowDisposableTransient: true));
ControllerContainer.RegisterMany<INews, NewsManager>(setup: Setup.With(allowDisposableTransient: true));
}
注册依赖性
public static class RegisterDependencies
{
public static Container container;
public static void Initialize()
{
container = new Container(rules => rules
.WithDefaultReuseInsteadOfTransient(Reuse.InWebRequest)
.WithoutThrowOnRegisteringDisposableTransient()
.WithoutImplicitCheckForReuseMatchingScope());
container.Register<INewsManager, NewsManager>();
container.Register<IGetNews, NewsManager>();
container.Register<IAddNews, NewsManager>();
container.Register<ILoggingService, Logger>();
container.Register<NewsController>(made: Made.Of(() => new NewsController
(Arg.Of<ILoggingService>(), Arg.Of<IGetNews>(), Arg.Of<IAddNews>(),
Arg.Of<INewsManager>())));
}
}
public static class RegisterDependencies
{
public static IContainer controllerContainer;
public static void InitializeControllerContainer(IContainer ControllerContainer)
{
ControllerContainer.RegisterMany<ILoggingService, Logger>(setup: Setup.With(allowDisposableTransient: true));
ControllerContainer.RegisterMany<INews, NewsManager>(setup: Setup.With(allowDisposableTransient: true));
}
好的,这是我想到的 在上面的问题更新:下,您将看到使用WebAPIConfig自动注册和解析依赖项的代码。您需要使用NuGet和DryIoc提供的DryIoc.WebAPI包 为了能够交换测试实现,您需要为测试/模拟依赖项创建一个类。您可以只使用上面的RegisterDependencies,但注册存根或模拟,而不是生产实现 然后,您的测试类(我使用的是xUnit)将如下所示,尽管不必担心构造函数中的AutoMapper部分:
public class NewsControllerTests
{
private IContainer _testContainer;
private NewsController _controller;
public NewsControllerTests()
{
Mapper.Initialize(config =>
{
config.CreateMap<News, NewsDto>();
config.CreateMap<NewsDto, News>();
});
_testContainer = RegisterTestDependencies.testContainer = new Container(rules => rules.With(FactoryMethod.ConstructorWithResolvableArguments)).WithWebApi(
new HttpConfiguration(), throwIfUnresolved: type => type.IsController());
RegisterTestDependencies.InitializeTestContainer(_testContainer);
}
[Fact]
void GetNews_WithoutId_ReturnsAllNewsItems()
{
//Arrange
using (var scope = _testContainer.OpenScope(Reuse.WebRequestScopeName))
{
_controller = scope.Resolve<NewsController>();
//Act
var getNewsResult = _controller.GetNews() as OkNegotiatedContentResult<List<NewsDto>>;
//Assert
getNewsResult.Content.Should().AllBeOfType<NewsDto>();
}
}
}
公共类NewsControllerTests
{
专用IContainer_testContainer;
专用新闻控制器(newcontroller);;
公共新闻控制测试()
{
初始化(配置=>
{
config.CreateMap();
config.CreateMap();
});
_testContainer=RegisterTestDependencies.testContainer=新容器(规则=>rules.With(FactoryMethod.ConstructorWithResolvableArguments)).WithWebApi(
新的HttpConfiguration(),throwIfUnresolved:type=>type.IsController();
RegisterTestDependencies.InitializeTestContainer(_testContainer);
}
[事实]
void GetNews\u without id\u ReturnsAllNewsItems()
{
//安排
使用(var scope=_testContainer.OpenScope(Reuse.WebRequestScopeName))
{
_controller=scope.Resolve();
//表演
var getNewsResult=_controller.GetNews()作为OKNegatedContentResult;
//断言
getNewsResult.Content.Should().AllBeOfType();
}
}
}
public class NewsControllerTests
{
private IContainer _testContainer;
private NewsController _controller;
public NewsControllerTests()
{
Mapper.Initialize(config =>
{
config.CreateMap<News, NewsDto>();
config.CreateMap<NewsDto, News>();
});
_testContainer = RegisterTestDependencies.testContainer = new Container(rules => rules.With(FactoryMethod.ConstructorWithResolvableArguments)).WithWebApi(
new HttpConfiguration(), throwIfUnresolved: type => type.IsController());
RegisterTestDependencies.InitializeTestContainer(_testContainer);
}
[Fact]
void GetNews_WithoutId_ReturnsAllNewsItems()
{
//Arrange
using (var scope = _testContainer.OpenScope(Reuse.WebRequestScopeName))
{
_controller = scope.Resolve<NewsController>();
//Act
var getNewsResult = _controller.GetNews() as OkNegotiatedContentResult<List<NewsDto>>;
//Assert
getNewsResult.Content.Should().AllBeOfType<NewsDto>();
}
}
}