using System.Collections.Generic;
static void Main(string[] args)
var ticket = new Ticket();
static readonly TicketStore TicketStore = new TicketStore();
public class Ticket : IModel
public int ID { get; set; }
public int UserID { get; set; }
public string Status { get; set; }
public List<Requirement> Requirements { get; set; }
public int? ID { get; set; }
public string Description { get; set; }
public class User : IModel
public int ID { get; set; }
public string Email { get; set; }
private readonly Repository<Ticket, MockTicketDatabase> _repository;
private readonly TicketPreSaver _preSaver;
private readonly TicketPostSaver _postSaver;
_repository = new Repository<Ticket, MockTicketDatabase>();
_preSaver = new TicketPreSaver();
_postSaver = new TicketPostSaver();
public Ticket Add(Ticket ticket)
_preSaver.Execute(ticket);
_postSaver.Execute(ticket);
public Ticket Update(Ticket ticket)
_preSaver.Execute(ticket);
_repository.Update(ticket);
_postSaver.Execute(ticket);
public class TicketPreSaver
private readonly UserStore _userStore;
_userStore = new UserStore();
public void Execute(Ticket ticket)
if (ticket.Requirements.Count > 10)
throw new Exception("A ticket cannot have more than 10 requirements");
if (!_userStore.Exists(ticket.UserID))
throw new Exception("User does not exist");
public class TicketPostSaver
private readonly EmailService _emailService;
private readonly UserStore _userStore;
_emailService = new EmailService();
_userStore = new UserStore();
public void Execute(Ticket ticket)
if (ticket.Status == "New")
_emailService.SendEmail("admin@streetsolutions.com", $"Ticket #{ticket.ID} has been created.");
if (ticket.Status == "Closed")
var user = _userStore.Get(ticket.UserID);
_emailService.SendEmail(user?.Email, $"Your ticket #{ticket.ID} has been closed.");
public class Repository<T, TDataStore> where T : IModel, new() where TDataStore : IDataStore<T>, new()
private readonly IDataStore<T> _database;
_database = new TDataStore();
return _database.Items.SingleOrDefault(x => x.ID == ID);
item.ID = !_database.Items.Any() ? 1 : _database.Items.Select(x => x.ID).Max() + 1;
_database.Items.Add(item);
public void Update(T item)
var existingItem = _database.Items.SingleOrDefault(x => x.ID == item.ID);
if (existingItem == null)
throw new Exception("Item not found");
var index = _database.Items.FindIndex(x => x.ID == item.ID);
_database.Items[index] = item;
private readonly Repository<User, MockUserDatabase> _repository;
_repository = new Repository<User, MockUserDatabase>();
public bool Exists(int userID)
return _repository.Get(userID) != null;
public User Get(int userID)
return _repository.Get(userID);
public class EmailService
public void SendEmail(string to, string message)
if (string.IsNullOrEmpty(to))
Console.WriteLine($"Email sent to {to} with message: {message}");
public class MockUserDatabase : IDataStore<User>
public List<User> Items { get; set; }
public MockUserDatabase()
new User(){ ID = 1000, Email = "admin@streetsolutions.com" },
new User(){ ID = 1002, Email = "john@streetsolutions.com" },
new User(){ ID = 1003, Email = "jane@streetsolutions.com" }
public class MockTicketDatabase : IDataStore<Ticket>
public List<Ticket> Items { get; set; }
public MockTicketDatabase()
Items = new List<Ticket>();
public interface IDataStore<T> where T : IModel, new()
public List<T> Items { get; set; }