2016-11-08 4 views
1

У меня есть общий RepositoryDecorator<T> декоратор. MyRepositoryDecoratorBase<T> и NoteRepository<Note> унаследованы от него.Autofac generic linking

IRepository<T> - это интерфейс, а Repository<T> - его реализация. Это также регистрируется с помощью Autofac, как показано в примере кода.

Пытается использовать autofac для генерации экземпляра MyRepositoryDecoratorBase каждый раз, когда запрашивается экземпляр NoteRepository.

Таким образом, я могу связать декораторы для решения сквозных задач, таких как ведение журнала.

Абстрактный декоратор

public abstract class RepositoryDecorator<TAggregate>:IRepository<TAggregate> 
    where TAggregate:AggregateRoot, new() 
{ 
    protected readonly IRepository<TAggregate> Repository; 

    protected RepositoryDecorator(IRepository<TAggregate> repository) 
    { 
     Repository = repository; 
    } 

    public virtual TAggregate GetById(Guid Id) 
    { 
     return Repository.GetById(Id); 
    } 

    public virtual void Save(TAggregate aggregate) 
    { 
     Repository.Save(aggregate); 
    } 

} 

Родовой LoggingDecorator

public class MyRepositoryDecoratorBase<T>:RepositoryDecorator<T> where T : AggregateRoot, new() 
{ 
    private DateTime _commitStartTime; 

    public MyRepositoryDecoratorBase(IRepository<T> repository) : base(repository) 
    { 
    } 

    public override T GetById(Guid Id) 
    { 
     BeforeLoadAggregate(Id); 
     var result = base.GetById(Id); 
     AfterLoadingAggregate(result); 
     return result; 
    } 

    public override void Save(T aggregate) 
    { 
     BeforeSaveAggregate(aggregate); 
     base.Save(aggregate); 
     AfterSavingAggregate(aggregate); 
    } 

    protected void BeforeLoadAggregate(Guid id) 
    { 
     Console.ForegroundColor = ConsoleColor.Red; 
     Console.WriteLine($"Loading {id} ..."); 
     Console.ForegroundColor = ConsoleColor.White; 
    } 

    protected void AfterLoadingAggregate(T aggregate) 
    { 
     Console.ForegroundColor = ConsoleColor.Red; 
     Console.WriteLine($"Loaded {aggregate.GetType()} ..."); 
     Console.ForegroundColor = ConsoleColor.White; 
    } 

    protected void BeforeSaveAggregate(T aggregate) 
    { 
     _commitStartTime = DateTime.Now; 
     Console.WriteLine($"Trying to commit {aggregate.GetUncommittedChanges().Count()} events to storage."); 
    } 

    protected void AfterSavingAggregate(T aggregate) 
    { 
     Console.WriteLine($"Committed in {DateTime.Now.Subtract(_commitStartTime).TotalMilliseconds} ms."); 
    } 
} 

Примечание декоратор

public class NoteRepository:RepositoryDecorator<Note> 
{ 
    public NoteRepository(IRepository<Note> repository) : base(repository) 
    { 

    } 

    public override void Save(Note aggregate) 
    { 
     LogManager.Log("Saving Note...", LogSeverity.Information); 
     base.Save(aggregate); 
     LogManager.Log("Note Saved...", LogSeverity.Information); 
    } 
} 

Примечание: Я использую это зарегистрировать Repository базовую реализацию для IRepository

  //This will resolve and bind storage types to a concrete repository of <T> as needed 
     builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).SingleInstance(); 

Я посмотрел на решение в Autofac - Register multiple decorators

Но не мог заставить его работать. У меня такое чувство, что моя общая регистрация репозитория мешает.

Следующие работы, но я хочу связать несколько Декораторов автоматически без жесткого кодирования.

NoteRepository rep = new NoteRepository(new MyRepositoryDecoratorBase<Note>(container.Resolve<IRepository<Note>>())); 

ответ

0

Я получил это работает следующим образом

 //This will resolve and bind storage types to a concrete repository of <T> as needed 
     builder.RegisterGeneric(typeof(Repository<>)) 
     .Named("handler",typeof(IRepository<>)) 
     .SingleInstance(); 

     //This will bind the decorator 
     builder.RegisterGenericDecorator(
     typeof(MyRepositoryDecorator<>),typeof(IRepository<>),fromKey: "handler"); 

     //Register NoteRepository 
     builder.RegisterType<NoteRepository>(); 

И использовать его

 //Get ioc container to create our repository 
     NoteRepository rep = resolver.Resolve<NoteRepository>(); 
Смежные вопросы