Autofac 通用装饰器链接

Autofac generic decorator linking

我有一个通用的 RepositoryDecorator<T> 装饰器。 MyRepositoryDecoratorBase<T>NoteRepository<Note> 继承自它。

IRepository<T> 是一个接口,Repository<T> 是它的一个实现。这也是使用 Autofac 注册的,如代码示例所示。

每次请求 NoteRepository 实例时,都尝试使用 autofac 生成 MyRepositoryDe​​coratorBase 实例。

这样我就可以 link 装饰器来处理像日志记录这样的横切问题。

抽象装饰器

    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);
    }
}

注意:我正在使用它来为 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

中的解决方案

但无法正常工作。我感觉我的 Repository 通用注册有问题。

下面的工作,但我想 link 多个装饰器自动无需硬编码。

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

我得到它的工作方式如下

        //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>();