C# 如何使用DryIoc解决WebAPI控制器的依赖关系

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

我一直在阅读文档,对于如何实现这一点,我有点困惑。我有一个名为NewsController的WebAPI控制器,我将在下面列出。它有一个构造函数,当前有三个依赖项。我已经为DryIoc创建了一个静态类,因此我可以在整个项目中全局使用它,并在启动时初始化它

我想做的是在我的DryIoc类中注册控制器及其依赖项,然后在NewsController中以某种方式解决这个问题。我想这样做的原因是,当我开始测试时,我可以让测试项目更改注册控制器的范围,并使用存根或模拟实现

注册依赖性

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>();

        }


    }
}