【问题标题】:How to do dependency injection on a noncontroller in asp.net core?如何在 asp.net 核心中的非控制器上进行依赖注入?
【发布时间】:2021-03-29 23:32:31
【问题描述】:

我正在尝试在不使用实体框架的情况下为我的 redis 数据库创建上下文。我的连接依赖于ConnectionMultiplexer 类,因此对于单元测试,我尝试使用依赖注入。如果没有 ConnectionMultiplexer 参数,我不确定如何为我的上下文创建 using 语句。

我做依赖注入错了吗?如何重组以便我可以正确使用“使用”上下文并让它为我解决依赖关系?

GameSession.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using StackExchange.Redis;

namespace Bored.GameService.GameSession
{
    public class GameSessionContext : IGameSession, IDisposable
    {
        private IDatabase conn;
        private readonly IConnectionMultiplexer _muxer;

        public GameSessionContext(IConnectionMultiplexer muxer)
        {
            _muxer = muxer;
            string connectionString = Startup.Configuration.GetConnectionString("redis");
            _muxer = ConnectionMultiplexer.Connect(connectionString);
            //conn = muxer.GetDatabase();
            //conn.StringSet("foo", "bar");
            //var value = conn.StringGet("foo");
            //Console.WriteLine(value);
        }

        public void GetGameState()
        {
            throw new NotImplementedException();
        }

        public void AddGameState()
        {
            throw new NotImplementedException();
        }

        public void Dispose()
        {
            _muxer.Dispose();
        }
    }
}

这是我在 startup.cs 中注册依赖项的地方

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IConnectionMultiplexer, ConnectionMultiplexer>();

    services.AddSignalR();

    services.AddCors(options =>
    {
        options.AddPolicy("ClientPermission", policy =>
        {
            policy.AllowAnyHeader()
                  .AllowAnyMethod()
                  .WithOrigins("http://localhost:3000")
                  .AllowCredentials();
        });
    });
}

这是我在 GameServiceAPI 类中使用它的方式:

using Bored.GameService.Clients;
using Bored.GameService.GameSession;
using Bored.GameService.Models;
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace Bored.GameService.GameServiceAPI
{
    public class GameServiceHub : Hub<IGameClient>
    {
        public Task SendMessage(GameMessage message)
        {
// Throws an error because GameSessionContext has no IConnectionMultiplexer parameter passed in.
            using (var context = new GameSessionContext())
            {
                // var gameState = context.GetGameState(context);
                // context.AddGameState(gameState);
                // Clients.All.ReceiveMessage(gameState);
            }
            return Clients.All.ReceiveMessage(message);
        }
    }
}

【问题讨论】:

  • 为什么不将 GameSessionContext 和 GameServiceHub 都注册到 DI 中,给 GameServiceHub 一个对 GameSessionContext 的构造函数依赖?
  • 我相信这会奏效。再看一遍之后,我试图为我的单元测试模拟的方法是静态的,接口没有它,所以我相信除了 DI 之外我还有其他问题。
  • 我认为我最好的方法是结合您的答案和stackoverflow.com/a/28326983/7331107,我在其中创建了一个包装器,用于与 redis 交互并仅处理它。谢谢!
  • @DavidBrowne-Microsoft 我将发布我为使其工作而编写的代码,如果你想复制它并做出自己的答案,我会接受你的,因为这有助于修复它!

标签: c# asp.net-core dependency-injection


【解决方案1】:

感谢@DavidBrowne 建议向 DI 注册 GameServiceHub 和 GameSessionContext。

这是我用来让它工作的代码:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect(Configuration.GetConnectionString("redis")));
    services.AddScoped<IGameSessionContext, GameSessionContext>();

    services.AddSignalR();

    services.AddCors(options =>
    {
        options.AddPolicy("ClientPermission", policy =>
        {
            policy.AllowAnyHeader()
                  .AllowAnyMethod()
                  .WithOrigins("http://localhost:3000")
                  .AllowCredentials();
        });
});

GameSessionContext.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using StackExchange.Redis;

namespace Bored.GameService.GameSession
{
    public class GameSessionContext : IGameSessionContext
    {
        private IDatabase conn;
        private readonly IConnectionMultiplexer _muxer;

        
        public GameSessionContext(IConnectionMultiplexer muxer)
        {
            _muxer = muxer;
        }

        public string GetGameState()
        {
            conn = _muxer.GetDatabase();
            conn.StringSet("foo", "Here's game state");
            return conn.StringGet("foo");
        }

        public void AddGameState()
        {
            throw new NotImplementedException();
        }
    }
}

GameServiceHub.cs

using Bored.GameService.Clients;
using Bored.GameService.GameSession;
using Bored.GameService.Models;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Threading.Tasks;

namespace Bored.GameService.GameServiceAPI
{
    public class GameServiceHub : Hub<IGameClient>
    {
        private IGameSessionContext _context;
        public GameServiceHub(IGameSessionContext context)
        {
            _context = context;
        }

        public Task SendMessage(GameMessage message)
        {
            var state = _context.GetGameState();
            Console.WriteLine(state);
                // var gameState = context.GetGameState(context);
                // context.AddGameState(gameState);
            return Clients.All.ReceiveMessage(message);
        }
    }
}

【讨论】:

    猜你喜欢
    • 2017-05-27
    • 2019-06-07
    • 2018-01-03
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 2020-04-04
    相关资源
    最近更新 更多