I am working on a very simplified proof of concept (POC).
Separation of concerns should be achieved in this project, so that in the future we have flexibility in respect of what data source we use (hence no UI
in this POC) .
- The
BLL
has a POCOFruit
class, the repository interface it expects its data sources to implement, and aFruitService
class, whose responsibility is to return a string that will be used to label the fruit. - The
DAL
returns a fruit when a key is supplied via a repository.
I want check that the code applies the SOLID
principle of Dependency Inversion (DIP
), so that the higher order BLL
does not depend on the DAL
- but rather DAL
depends on BLL
.
Solution structure:
BLL
classes:
1.Fruit POCO:
namespace DapperRepository_SingleProject.BusinessLogicLayer
{
public class Fruit
{
public int FruitKey { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public decimal Price { get; set; }
}
}
2.Generalised repository interface:
namespace DapperRepository_SingleProject.BusinessLogicLayer
{
public interface IRepository<T> where T : class
{
T GetByKey(int key);
}
}
3.FruitService
class with a single method to return a string, for a label - here I have attempted to implement constructor injection:
class FruitService
{
private IRepository<Fruit> FruitRepo = null;
public FruitService(IRepository<Fruit> fruitRepo)
{
FruitRepo = fruitRepo;
}
public string PrintLabel(int fruitKey)
{
Fruit f = FruitRepo.GetByKey(fruitKey);
return string.Concat(f.Name.ToString(), " priced at ", f.Price.ToString());
}
}
DAL
has a Repository class that implements the repository interface specified in the BLL
:
using System.Linq;
using Dapper;
using System.Data;
using System.Configuration;
using System.Data.SqlClient;
using DapperRepository_SingleProject.BusinessLogicLayer;
namespace DapperRepository_SingleProject.DataAccessLayer
{
public class FruitRepository : IRepository<Fruit>
{
private IDbConnection dbConnection = null;
public FruitRepository()
{
dbConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["xxx"].ConnectionString);
}
public Fruit GetByKey(int key)
{
Fruit fruit = null;
string sql = "SELECT * FROM FruitInfo.dbo.tb_Fruit WHERE FruitKey=@Key";
var queryResult = dbConnection.Query<Fruit>(sql, new { Key = key });
if (queryResult != null)
{
fruit = queryResult.FirstOrDefault();
}
return fruit;
}
}
}
Data is as follows:
USE FruitInfo;
CREATE TABLE dbo.tb_Fruit
(
FruitKey int not null,
Name varchar(25),
Color varchar(25),
Price money
);
ALTER TABLE dbo.tb_Fruit
ADD CONSTRAINT PK_tb_Fruit_FruitKey PRIMARY KEY CLUSTERED (FruitKey);
INSERT INTO FruitInfo.dbo.tb_Fruit
values
(1, 'Apple', 'Red', 10),
(2, 'Orange','Orange', 20),
(3, 'Pear', 'Green', 15);
Program.cs
I use both the namespaces of DAL
and BLL
with a method Orchestrator
that is my attempt at the injection:
using System;
using DapperRepository_SingleProject.DataAccessLayer;
using DapperRepository_SingleProject.BusinessLogicLayer;
namespace DapperRepository_SingleProject
{
class Program
{
FruitRepository fruitRepository = null;
static void Main(string[] args)
{
Program p = new Program();
p.Orchestrator();
}
public void Orchestrator()
{
fruitRepository = new FruitRepository();
FruitService fs = new FruitService(fruitRepository); //<<attempt at constructor injection
Console.WriteLine(fs.PrintLabel(1));
Console.WriteLine("press a key");
Console.ReadKey();
}
}
}
Two questions for review:
Does the above comply with the
Dependency-Inversion Principle
? I amusing
theBLL
namespace in theDAL
classes, but not theDAL
namespace in theBLL
so I am assuming it complies? If it does not comply with this principle then what changes are required so it does?In the
Orchestration.cs
andFruitService.cs
classes I've tried to use Dependency Injection - is my implementation correct?