Skip to content

Instantly share code, notes, and snippets.

@worldspawn
Created May 19, 2015 01:24
Show Gist options
  • Save worldspawn/c8472291e357c3ef29ba to your computer and use it in GitHub Desktop.
Save worldspawn/c8472291e357c3ef29ba to your computer and use it in GitHub Desktop.
Protected+Audited domain actions
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Manager
{
class Program
{
static void Main(string[] args)
{
IDatabase database = null;
var managerFactory = new ManagerFactory(database);
var manager = managerFactory.Create<User>();
var user = new User();
manager.Manage(user,
new User.Tasks.ChangePassword("password"));
}
}
public class ManagerFactory
{
private readonly IDatabase _database;
public ManagerFactory(IDatabase database)
{
_database = database;
}
public Manager<TModel> Create<TModel>()
{
return new Manager<TModel>(_database);
}
}
public interface IDatabase
{
void Save(object obj);
void Save(object[] objects);
}
public class Manager<TModel>
{
private readonly IDatabase _database;
public Manager(IDatabase database)
{
_database = database;
}
public void Manage(TModel model, params ManagerTask<TModel>[] tasks)
{
Manage(model, tasks.AsEnumerable());
}
public void Manage(TModel model, IEnumerable<ManagerTask<TModel>> tasks)
{
var audits = tasks.SelectMany(t => t.Run(model));
_database.Save(audits);
}
}
public abstract class ManagerTask<TModel>
{
public IEnumerable<TaskAudit> Run(TModel model)
{
OnBeforeExecute();
var audits = Execute(model);
OnAfterExecute();
return audits;
}
protected virtual void OnBeforeExecute()
{
}
protected abstract IEnumerable<TaskAudit> Execute(TModel model);
protected virtual void OnAfterExecute()
{
}
}
public class TaskAudit
{
public TaskAudit(object task, params TaskTarget[] targets)
{
ExecutedAt = DateTime.UtcNow;
Task = task.GetType();
Targets = targets;
}
public IEnumerable<TaskTarget> Targets { get; set; }
public Type Task { get; private set; }
public DateTime ExecutedAt { get; private set; }
public class TaskTarget
{
public TaskTarget(Type type, Guid id)
{
Type = type;
Id = id;
}
public Type Type { get; private set; }
public Guid Id { get; private set; }
public static implicit operator TaskTarget(Model model)
{
return new TaskTarget(model.GetType(), model.Id);
}
}
}
public abstract class Model
{
protected Model()
{
}
protected Model(Guid id)
{
Id = id;
}
public Guid Id { get; protected set; }
}
public class User : Model
{
public User()
{
}
public User(Guid id) : base(id)
{
}
public string Password { get; private set; }
public static class Tasks
{
public class ChangePassword : ManagerTask<User>
{
private readonly string _password;
public ChangePassword(string password)
{
_password = password;
}
protected override IEnumerable<TaskAudit> Execute(User model)
{
model.Password = _password;
yield return new TaskAudit(this, model);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment