简体   繁体   中英

How to do dependency injection on a noncontroller in asp.net core?

I'm trying to create a context for my redis database without using Entity Framework. My connection depends on a ConnectionMultiplexer class, so for unit testing I'm trying to use dependency injection. I'm not sure how to create the using statement for my context without the ConnectionMultiplexer parameter.

Am I doing dependency injection wrong? How can I restructure so I can use the "using" context correctly and have it resolve the dependency for me?

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

Here is where I'm registering the dependency in my 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();
        });
    });
}

Here is how I'm using it in my GameServiceAPI class:

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

Thanks to @DavidBrowne's suggestion for registering both the GameServiceHub and GameSessionContext with DI.

Here's the code I used to get this to work:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM