Autofac通用装饰器链接

时间:2016-11-08 16:19:51

标签: c# inversion-of-control autofac

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

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

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

通过这种方式,我可以将装饰器与日志记录等交叉问题联系起来。

抽象装饰

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

}

Generic 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

中的解决方案

但无法让它发挥作用。我有一种感觉,我的存储库的通用注册正在阻碍。

以下有效但我想自动链接多个装饰器而不对其进行硬编码。

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

1 个答案:

答案 0 :(得分: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>();