У меня есть общий 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>>()));