c# – Is this wrong Strategy Pattern Implementation?


I’ve read a lot about Strategy Pattern, and came with a little bit different(simple) implementation.

Well, I’m wondering – current implementation is wrong and should be avoided, or is it ok?

public interface ICartStrategy
{
    ICartService GetService(UserStatus userStatus);
}

public class CartStrategy : ICartStrategy
{
    private readonly IEnumerable<ICartService> _cartServices;

    public CartStrategy(IEnumerable<ICartService> cartServices)
    {
        _cartServices = cartServices;
    }

    public ICartService GetService(UserStatus userStatus)
    {
        return _cartServices.FirstOrDefault(t => t.UserStatus == userStatus);
    }
}

public interface ICartService
{
    UserStatus UserStatus { get; }

    Task CreateAsync(CartModel model);

    Task<CartModel> GetAsync();
    
    // etc...
}

public class CartAnonymousService : ICartService
{
    private readonly ApplicationDbContext _context;
    private readonly ICookieManager _cookieManager;

    public UserStatus UserStatus { get => UserStatus.Anonymous; }

    public CartAnonymousService(ApplicationDbContext context, ICookieManager cookieManager)
    {
        _context = context;
        _cookieManager = cookieManager;
    }

    public async Task CreateAsync(CartModel model)
    {
        // some logic...
    }

    public async Task<CartModel> GetAsync()
    {
        // some logic...
    }
    
    // etc...
}

public class CartAuthenticatedService : ICartService
{
    private readonly ApplicationDbContext _context;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public UserStatus UserStatus { get => UserStatus.Authenticated; }

    public CartAuthenticatedService(ApplicationDbContext context, IHttpContextAccessor httpContextAccessor)
    {
        _context = context;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task CreateAsync(CartModel model)
    {
        // some logic...
    }

    public async Task<CartModel> GetAsync()
    {
        // some logic...
    }
    
    // etc...
}

and Startup

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<ICartStrategy, CartStrategy>();
        services.AddTransient<ICartService, CartAnonymousService>();
        services.AddTransient<ICartService, CartAuthenticatedService>();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {

    }
}

and use case in Controller

public class CartController : Controller
{
    private readonly ICartStrategy _cartStrategy;

    public CartController(ICartStrategy cartStrategy)
    {
        _cartStrategy = cartStrategy;
    }

    (HttpPost)
    public async Task<IActionResult> Create(CartModel model)
    {
        var userStatus = User.GetUserStatus();

        await _cartStrategy.GetService(userStatus).CreateAsync(model);

        return View();
    }

    (HttpGet)
    public async Task<IActionResult> Get()
    {
        var userStatus = User.GetUserStatus();

        var model = await _cartStrategy.GetService(userStatus).GetAsync();

        return View(model);
    }
}