jeg har som udgangspunkt brugt DDD til og designe dette program, da det virker til og være den måde man har adgang til de forskellige plugins og biblioteker.
siden et plugin kun skal kunne designes efter et abstracts bibliotek, burde det også gøre det lettere og vedligeholde et enkelt plugin, da det ikke er afhængigt af andet.
jeg fik lige lavet et eksempel selv, som jeg tænker at min kode burde se ud hvis jeg skal overholde mine krav.
using System;
using System.Threading.Tasks;
using DDD.Abstracts;
/// <summary>
/// Base Program Program.exe
///
/// Base kender til Abstracts og alle plugins, so de kan frit blive brugt her.
/// </summary>
namespace DDD
{
class Program
{
static object _consoleLock = new object();
static IMessageMonitor smsmonitor = new DDD.Tools.SMSs.SMSMonitor();
static IMessageMonitor emailmonitor = new DDD.Tools.Emails.EmailMonitor();
static IMessageProcessor processor = new DDD.Tools.MessageProcessor();
static void Main(string[] args)
{
smsmonitor.Message += OnMessage;
emailmonitor.Message += OnMessage;
smsmonitor.Listen();
emailmonitor.Listen();
}
private static void OnMessage(object sender, MessageEventArgs e)
{
lock(_consoleLock){
var message = e.Message;
processor.Process(message);
}
}
}
}
/// <summary>
/// (Producer) SMS Plugin SMS.Lib.dll
/// </summary>
namespace DDD.Tools.SMSs
{
/// <summary>
/// Process som tjekker extern api for nye sms'er og sender dem ind i systemet som et event
/// </summary>
public class SMSMonitor : IMessageMonitor
{
static Random rnd = new Random();
public event EventHandler<MessageEventArgs> Message;
/// <summary>
/// Intern Methode til og Trigger Message Event
/// </summary>
private void TriggerMessage(SMS message){
Message?.Invoke(this,new MessageEventArgs(new SMSAdapter(message)));
}
/// <summary>
/// MOCK Privat Methode til og lave et tilfældigt dummy nummer
/// </summary>
private string CreateDanishNumber(){
return $"+45 {string.Format("{0:00-000-000}",rnd.Next(10_00_00_00,99_99_99_99+1))}";
}
/// <summary>
/// laver en random MOCK SMS
/// </summary>
private SMS CreateRandom(){
string[] networks = new[] {"telia","tdc","sonofon"};
return new SMS(networks[rnd.Next(networks.Length)],CreateDanishNumber(),CreateDanishNumber(),"Hello, this is a test SMS");
}
/// <summary>
/// starter process til og lytte efter nye sms'er
/// </summary>
public void Listen(){
Run();
}
/// <summary>
/// henter noget MOCK og sender dem ud som events
/// </summary>
public void Run(){
TriggerMessage(CreateRandom());
TriggerMessage(CreateRandom());
}
}
/// <summary>
/// Model som kan holde data omkring en smsbesked
/// Simplificeret
/// </summary>
public class SMS
{
public string Network {get;}
public string FromNumber {get;}
public string ToNumber {get;}
public string Message {get;}
public SMS(string network, string from, string to, string message){
Network = network;
FromNumber = from;
ToNumber = to;
Message = message;
}
}
/// <summary>
/// Adapter-wrapper som adapter SMS til en IMessage
/// </summary>
public class SMSAdapter : IMessage
{
private SMS _sms;
public string From => _sms.FromNumber;
public string To => _sms.ToNumber;
public string Subject => "SMS Message";
public string Body => _sms.Message;
public string SourceType => "SMS";
public SMSAdapter(SMS sms){
_sms = sms;
}
}
}
/// <summary>
/// (Producer) SMS Plugin Email.Lib.dll
/// </summary>
namespace DDD.Tools.Emails
{
/// <summary>
/// Process som tjekker ekstern api for Emails, og sender dem ind i systemet som events
/// </summary>
public class EmailMonitor : IMessageMonitor
{
static Random rnd = new Random();
public event EventHandler<MessageEventArgs> Message;
/// <summary>
/// Intern methode til og trigger et Message Event
/// </summary>
/// <param name="email"></param>
private void TriggerMessage(Email email){
Message?.Invoke(this,new MessageEventArgs(new EmailAdapter(email)));
}
/// <summary>
/// Laver en radom MOCK email
/// </summary>
Email CreateRandom(){
// Laver lidt MOCK data at vælge fra
string[] users = new[]{"test","admin","root","webmarster"};
string[] domains = new[]{"localhost","example.com","eksempel.dk"};
string[] subjects = new[]{"All your base are belong to us","A Winner Is You!","Arrow To The Knee"};
var emailto = users[rnd.Next(users.Length)]+"@"+domains[rnd.Next(domains.Length)];
var emailfrom = users[rnd.Next(users.Length)]+"@"+domains[rnd.Next(domains.Length)];
var subject = subjects[rnd.Next(subjects.Length)];
return new Email(emailfrom,emailto,null,null,subject,"Hello, this is a test Email");
}
/// <summary>
/// Henter noget MOCK data, og trigger dem igennem events
/// </summary>
public void Run(){
TriggerMessage(CreateRandom());
TriggerMessage(CreateRandom());
}
/// <summary>
/// Starter med og lytte efter nye emails
/// </summary>
public void Listen()
{
Run();
}
}
/// <summary>
/// Simplificeret Email Model
/// </summary>
public class Email
{
public string From {get;}
public string To {get;}
public string CC {get;}
public string BCC {get;}
public string Subject {get;}
public string Body {get;}
public Email(string from, string to, string cc, string bcc, string subject, string body){
From = from;
To = to;
CC = cc;
BCC = bcc;
Subject = subject;
Body = body;
}
}
/// <summary>
/// Adapter-wrapper som adapter Email til IMessage
/// </summary>
public class EmailAdapter : IMessage
{
private Email _email;
public string From => _email.From;
public string To => _email.To;
public string Subject => _email.Subject;
public string Body => _email.Body;
public string SourceType => "Email";
public EmailAdapter(Email email){
_email = email;
}
}
}
/// <summary>
/// (Consumer) IMessageProcessor Plugin Processor.Messages.Console.lib.dll
/// </summary>
namespace DDD.Tools
{
/// <summary>
/// Message Processor som skriver message ud til Consollen
/// </summary>
public class MessageProcessor : IMessageProcessor
{
public void Process(IMessage message)
{
Console.WriteLine("!New Message!");
Console.WriteLine($"Agent: {message.SourceType}");
Console.WriteLine($"From: {message.From}");
Console.WriteLine($"To: {message.To}");
Console.WriteLine($"Subject: {message.Subject}");
Console.WriteLine(message.Body);
}
}
}
/// <summary>
/// Abstracts (abstracts.library.dll)
/// </summary>
namespace DDD.Abstracts
{
/// <summary>
/// er godt nok en klasse, men det virkede mest logisk og alligevel have den her
/// </summary>
public class MessageEventArgs
{
public IMessage Message {get;}
public MessageEventArgs(IMessage message){
Message = message;
}
}
/// <summary>
/// repræsentere en process som kan overvåge beskedder fra intern eller ekstern kilde, ved ny besked trigger den et event på sig selv, som andre kan registrere sig til
/// </summary>
public interface IMessageMonitor
{
/// <summary>
/// Event som bliver triggered når der kommer en ny besked
/// </summary>
event EventHandler<MessageEventArgs> Message;
/// <summary>
/// Starter lytte process, burde nok være en async task, men det er jo kun et eksempel
/// </summary>
void Listen();
}
/// <summary>
/// Model som indeholder en besked
/// </summary>
public interface IMessage
{
string From {get;}
string To {get;}
string Subject {get;}
string Body {get;}
string SourceType {get;}
}
/// <summary>
/// Process som behandler en Besked
/// </summary>
public interface IMessageProcessor
{
void Process(IMessage message);
}
}