DEV Community

FaithInErrorsZORO
FaithInErrorsZORO

Posted on

Getting started with C# SOLID Principles

In my repo I've got this `using MusicLab.Projects.Models;
using System.Collections.Generic;
using System.Linq;

namespace MusicLab.Projects.Data
{
public class InstrumentRepository : IInstrumentRepository
{
private readonly MusicDbContext _context;

public InstrumentRepository(MusicDbContext context)
{
    _context = context;
}

public List<Instrument> GetInstruments()
{
    return _context.GetInstruments();
}

public List<Instrument> GetInstrumentsByCategory(string category)
{
    return _context.GetInstruments().Where(i => i.Category == category).ToList();
}

public Instrument FindById(int id)
{
    return _context.FindById(id);
}

public void Add(Instrument i)
{
    _context.Add(i);
}

public void Update(Instrument i)
{
    _context.Update(i);
}

public void Remove(int id)
{
    _context.Remove(id);
}
Enter fullscreen mode Exit fullscreen mode

}
}`

and then in my interface :

C#
using MusicLab.Projects.Models;

namespace MusicLab.Projects.Utils
{
public interface ITaxCalculator
{
decimal CalculateTax(Instrument instrument);
}

public class DefaultTaxCalculator : ITaxCalculator
{
    public decimal CalculateTax(Instrument instrument)
    {
        // Standard tax calculation replacing the static method
        return instrument.Price * 0.15m; 
    }
}
Enter fullscreen mode Exit fullscreen mode

}
and then my csv exporter :

C#
using MusicLab.Projects.Models;
using System.Collections.Generic;
using System.Text;

namespace MusicLab.Projects.Utils
{
public interface ICsvExporter
{
string ExportInstrumentsCsv(List instruments);
}

public class CsvExporter : ICsvExporter
{
    public string ExportInstrumentsCsv(List<Instrument> instruments)
    {
        var sb = new StringBuilder();
        sb.AppendLine("Id,Name,Price,Category");
        foreach (var i in instruments)
        {
            sb.AppendLine($"{i.Id},{i.Name},{i.Price},{i.Category}");
        }
        return sb.ToString();
    }
}
Enter fullscreen mode Exit fullscreen mode

}
and then the controller :

C#
using Microsoft.AspNetCore.Mvc;
using MusicLab.Projects.Data;
using MusicLab.Projects.Models;
using MusicLab.Projects.Utils;
using System.Collections.Generic;
using System.Text;

namespace MusicLab.Projects.Controllers
{
public class InstrumentsController : Controller
{
private readonly IInstrumentRepository _repository;
private readonly ICsvExporter _exporter;
private readonly ITaxCalculator _taxCalculator;

    public InstrumentsController(IInstrumentRepository repository, ICsvExporter exporter, ITaxCalculator taxCalculator)
    {
        _repository = repository;
        _exporter = exporter;
        _taxCalculator = taxCalculator;
    }

    public IActionResult Index(string category)
    {
        List<Instrument> instruments;

        if (!string.IsNullOrWhiteSpace(category))
        {
            instruments = _repository.GetInstrumentsByCategory(category);
        }
        else
        {
            instruments = _repository.GetInstruments();
        }

        return View(instruments);
    }

    public IActionResult Details(int id)
    {
        Instrument instrument = _repository.FindById(id);
        if (instrument == null) return NotFound();

        ViewData["Tax"] = _taxCalculator.CalculateTax(instrument);
        return View(instrument);
    }

    [HttpPost]
    public IActionResult Create(Instrument model)
    {
        if (model == null) return BadRequest("No data");

        // Replaced manual model.IsValid() with built-in ModelState validation
        if (!ModelState.IsValid) return BadRequest("Invalid instrument"); 

        _repository.Add(model);
        return Redirect("/Instruments/Index");
    }

    public IActionResult Export()
    {
        List<Instrument> instruments = _repository.GetInstruments();
        string csv = _exporter.ExportInstrumentsCsv(instruments);
        byte[] bytes = Encoding.UTF8.GetBytes(csv);
        return File(bytes, "text/csv", "instruments.csv");
    }
}
Enter fullscreen mode Exit fullscreen mode

}
and then program.cs :

C#
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using MusicLab.Projects.Data;
using MusicLab.Projects.Utils;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

// Register the mock DbContext as a Singleton so the list persists in memory
builder.Services.AddSingleton();

// Register dependencies for Dependency Injection
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddScoped();

var app = builder.Build();

app.UseRouting();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Instruments}/{action=Index}/{id?}");

app.Run();

Top comments (0)