Sunday, June 10, 2012

Utilizing the command pattern to support CQRS on top of a domain framework

Building on top of the domain framework I posted last time, I wanted to share a command pattern implementation I've come up with to try and make enabling CQRS scenarios easier.

Disclaimer: The code below carries no guarantees-- heck, it may not even work-- so use at your own risk.



    public interface Executable
    {
        void Execute();
    }


    public interface Command : Executable
    { }


    public interface Query : Executable
    { }


    public abstract class UnitOfWorkBasedCommand : UnitOfWorkBasedObject, Command
    {
        protected abstract void ExecuteCommand();


        public void Execute()
        { ExecuteCommand(); }


        public UnitOfWorkBasedCommand(UnitOfWork unitOfWork) : base(unitOfWork)
        { }
    }


    public abstract class UnitOfWorkBasedQuery : UnitOfWorkBasedObject, Query
    {
        protected abstract void ExecuteQuery();


        protected bool ShouldExecuteAsReadOnly
        { get; private set; }


        public void Execute()
        { ExecuteQuery(); }
        

        public UnitOfWorkBasedQuery(UnitOfWork unitOfWork, bool shouldExecuteAsReadOnly = true) : base(unitOfWork)
        { ShouldExecuteAsReadOnly = shouldExecuteAsReadOnly; }
    }


    public abstract class RepositoryAccessingCommand : UnitOfWorkBasedCommand
    {
        private readonly RepositoryFactory repositories = null;


        protected Repository<TEntity> GetRepositoryAddedToUnitOfWorkContexts<TEntity>() where TEntity : class, new()
        {
            var repository = repositories.Get<TEntity>();
            UnitOfWork.AddContext(repository);
            return repository;
        }


        protected ReadOnlyRepository<TEntity> GetReadOnlyRepositoryAddedToUnitOfWorkContexts<TEntity>() where TEntity : class, new()
        {
            var repository = repositories.GetReadOnly<TEntity>();
            UnitOfWork.AddContext(repository);
            return repository;
        }


        public RepositoryAccessingCommand(UnitOfWork unitOfWork, RepositoryFactory repositoryFactory) : base(unitOfWork)
        {
            repositories = repositoryFactory;
        }
    }


    public abstract class RepositoryAccessingQuery : UnitOfWorkBasedQuery
    {
        private readonly RepositoryFactory repositories = null;


        protected Repository<TEntity> GetRepositoryAddedToUnitOfWorkContexts<TEntity>() where TEntity : class, new()
        {
            var repository = repositories.Get<TEntity>();
            UnitOfWork.AddContext(repository);
            return repository;
        }


        protected ReadOnlyRepository<TEntity> GetReadOnlyRepositoryAddedToUnitOfWorkContexts<TEntity>() where TEntity : class, new()
        {
            var repository = repositories.GetReadOnly<TEntity>();
            UnitOfWork.AddContext(repository);
            return repository;
        }


        public RepositoryAccessingQuery(
            UnitOfWork unitOfWork, 
            RepositoryFactory repositoryFactory,
            bool shouldExecuteAsReadOnly = true
        ) : base(unitOfWork, shouldExecuteAsReadOnly)
        {
            repositories = repositoryFactory;
        }
    }
    

No comments:

Post a Comment