C # - Composición de objetos - Eliminación del código de placa de caldera

Contexto / pregunta

He trabajado en numerosos proyectos .NET que han sido requeridos para conservar los datos y por lo general terminé usando unRepositorio modelo. ¿Alguien sabe de una buena estrategia para eliminar tanto código repetitivo sin sacrificar la escalabilidad de la base de código?

Estrategia de herencia

Debido a que gran parte del código del Repositorio es la placa de la caldera y debe repetirse, normalmente creo una clase base para cubrir los aspectos básicos como el manejo de excepciones, el registro y el soporte de transacciones, así como algunos métodos básicos de CRUD:

public abstract class BaseRepository<T> where T : IEntity
{
    protected void ExecuteQuery(Action query)
    {
        //Do Transaction Support / Error Handling / Logging
        query();
    }       

    //CRUD Methods:
    public virtual T GetByID(int id){}
    public virtual IEnumerable<T> GetAll(int id){}
    public virtual void Add (T Entity){}
    public virtual void Update(T Entity){}
    public virtual void Delete(T Entity){}
}

Así que esto funciona bien cuando tengo un dominio simple, puedo crear rápidamente una clase de repositorio DRY para cada entidad. Sin embargo, esto comienza a descomponerse cuando el dominio se vuelve más complejo. Digamos que se introduce una nueva entidad que no permite actualizaciones. Puedo dividir las clases base y mover el método de actualización a una clase diferente:

public abstract class BaseRepositorySimple<T> where T : IEntity
{
    protected void ExecuteQuery(Action query);

    public virtual T GetByID(int id){}
    public virtual IEnumerable<T> GetAll(int id){}
    public virtual void Add (T entity){}
    public void Delete(T entity){}
}

public abstract class BaseRepositoryWithUpdate<T> :
    BaseRepositorySimple<T> where T : IEntity
{
     public virtual void Update(T entity){}
}

Esta solución no escala bien. Digamos que tengo varias Entidades que tienen un método común: archivo virtual público vacío (entidad T) {}

pero algunas Entidades que pueden archivarse también pueden actualizarse, mientras que otras no pueden. Entonces, mi solución de herencia se descompone, tendría que crear dos nuevas clases base para lidiar con este escenario.

Estrategia de competencia

He explorado el patrón de Compositon, pero esto parece dejar mucho código de placa de caldera:

public class MyEntityRepository : IGetByID<MyEntity>, IArchive<MyEntity>
{
    private Archiver<MyEntity> _archiveWrapper;      
    private GetByIDRetriever<MyEntity> _getByIDWrapper;

    public MyEntityRepository()
    {
         //initialize wrappers (or pull them in
         //using Constructor Injection and DI)
    }

    public MyEntity GetByID(int id)
    {
         return _getByIDWrapper(id).GetByID(id);
    }

    public void Archive(MyEntity entity)
    {
         _archiveWrapper.Archive(entity)'
    }
} 

El MyEntityRepository ahora está cargado con código repetitivo. ¿Hay alguna herramienta / patrón que pueda usar para generar esto automáticamente?

Si pudiera convertir el MyEntityRepository en algo como esto, creo que con mucho sería ideal:

[Implement(Interface=typeof(IGetByID<MyEntity>), 
    Using = GetByIDRetriever<MyEntity>)]      
[Implement(Interface=typeof(IArchive<MyEntity>), 
    Using = Archiver<MyEntity>)
public class MyEntityRepository
{
    public MyEntityRepository()
    {
         //initialize wrappers (or pull them in
         //using Constructor Injection and DI)
    }
}
Programación Orientada a Aspectos

Miré en el uso de un marco AOP para esto, específicamentePostSharp y ellosAspecto de la composición, que parece que debería hacer el truco, pero para usar un Repositorio tendré que llamar a Post.Cast <> (), que agrega un olor muy extraño al código. ¿Alguien sabe si hay una mejor manera de usar AOP para ayudar a deshacerse del código repetitivo del compositor?

Generador de código personalizado

Si todo lo demás falla, supongo que podría trabajar en la creación de un complemento Visual Studio del Generador de Código Personalizado que podría generar el código de la placa de la caldera en un archivo de código parcial. ¿Ya hay una herramienta por ahí que haría esto?

[Implement(Interface=typeof(IGetByID<MyEntity>), 
    Using = GetByIDRetriever<MyEntity>)]      
[Implement(Interface=typeof(IArchive<MyEntity>), 
    Using = Archiver<MyEntity>)
public partial class MyEntityRepository
{
    public MyEntityRepository()
    {
         //initialize wrappers (or pull them in
         //using Constructor Injection and DI)
    }
} 

//Generated Class file
public partial class MyEntityRepository : IGetByID<MyEntity>, IArchive<MyEntity>
{
    private Archiver<MyEntity> _archiveWrapper;      
    private GetByIDRetriever<MyEntity> _getByIDWrapper;

    public MyEntity GetByID(int id)
    {
         return _getByIDWrapper(id).GetByID(id);
    }

    public void Archive(MyEntity entity)
    {
         _archiveWrapper.Archive(entity)'
    }
} 
Métodos de extensión

Olvidé agregar esto cuando inicialmente escribí la pregunta (lo siento). También traté de experimentar con métodos de extensión:

public static class GetByIDExtenions
{
     public T GetByID<T>(this IGetByID<T> repository, int id){ }        
}

Sin embargo, esto tiene dos problemas: a) Tendría que recordar el espacio de nombres de la clase de métodos de extensión y agregarlo en todas partes yb) los métodos de extensión no pueden satisfacer las dependencias de la interfaz:

public interface IMyEntityRepository : IGetByID<MyEntity>{}
public class MyEntityRepository : IMyEntityRepository{}

Actualizar: HaríaPlantillas T4 ¿Ser una posible solución?

Respuestas a la pregunta(5)

Su respuesta a la pregunta