Autofac 通用装饰器链接
Autofac generic decorator linking
我有一个通用的 RepositoryDecorator<T>
装饰器。 MyRepositoryDecoratorBase<T>
和 NoteRepository<Note>
继承自它。
IRepository<T>
是一个接口,Repository<T>
是它的一个实现。这也是使用 Autofac 注册的,如代码示例所示。
每次请求 NoteRepository 实例时,都尝试使用 autofac 生成 MyRepositoryDecoratorBase 实例。
这样我就可以 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>();
我有一个通用的 RepositoryDecorator<T>
装饰器。 MyRepositoryDecoratorBase<T>
和 NoteRepository<Note>
继承自它。
IRepository<T>
是一个接口,Repository<T>
是它的一个实现。这也是使用 Autofac 注册的,如代码示例所示。
每次请求 NoteRepository 实例时,都尝试使用 autofac 生成 MyRepositoryDecoratorBase 实例。
这样我就可以 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>();