Dependency injection 多线程环境中的Ninject拦截
我正在尝试使用Ninject.Extensions.Interception.dynamicxproxy创建一个拦截器来记录方法完成时间 在单线程环境中,类似这样的工作方式:Dependency injection 多线程环境中的Ninject拦截,dependency-injection,ninject,ninject-interception,Dependency Injection,Ninject,Ninject Interception,我正在尝试使用Ninject.Extensions.Interception.dynamicxproxy创建一个拦截器来记录方法完成时间 在单线程环境中,类似这样的工作方式: public class TimingInterceptor : SimpleInterceptor { readonly Stopwatch _stopwatch = new Stopwatch(); private bool _isStarted; protected override vo
public class TimingInterceptor : SimpleInterceptor
{
readonly Stopwatch _stopwatch = new Stopwatch();
private bool _isStarted;
protected override void BeforeInvoke(IInvocation invocation)
{
_stopwatch.Restart();
if (_isStarted) throw new Exception("resetting stopwatch for another invocation => false results");
_isStarted = true;
invocation.Proceed();
}
protected override void AfterInvoke(IInvocation invocation)
{
Debug.WriteLine(_stopwatch.Elapsed);
_isStarted = false;
}
}
但是,在多线程场景中,这不起作用,因为秒表是在调用之间共享的。如何将StopWatch实例从BeforeInvoke传递到AfterInvoke,使其不会在调用之间共享 这在多线程应用程序中应该可以正常工作,因为每个线程都应该有自己的对象图。所以,当您开始处理某个任务时,您首先要解析一个新的图形,并且图形不应该从一个线程传递到另一个线程。这允许将什么是线程安全(什么不是)的知识集中到应用程序中连接所有内容的一个地方:线程 当您这样工作时,这意味着当您使用此拦截器来监视单例类(以及跨线程使用的类)时,每个线程仍将获得自己的拦截器(当其注册为瞬态时),因为每次解析时,您都会获得一个新的拦截器(即使您重用相同的“拦截器”实例) 然而,这确实意味着您必须非常小心地将这个被拦截的组件注入到其中,因为如果您将这个被拦截的对象注入到另一个单例中,您将再次遇到麻烦。这种特殊的“麻烦”被称为生活方式不匹配。这很容易让你不小心误解了你的容器,从而给自己带来麻烦,不幸的是Ninject没有可能警告你这一点 但请注意,如果您开始使用decorator而不是拦截器,您的问题将消失,因为使用decorator,您可以将所有内容保存在一个方法中。这意味着即使decorator也可以是单实例,而不会引起任何线程问题。例如:
//命令处理程序的时间交叉关注点
公共类TimingCommandHandlerDecorator:ICommandHandler
{
私有只读ICommandHandler装饰对象;
公共计时CommandHandlerDecorator(ICommandHandler decoratee)
{
this.decoree=decoree;
}
公共无效句柄(TCommand命令)
{
var stopwatch=stopwatch.StartNew();
this.decoree.Handle(命令);
Debug.WriteLine(秒表已过);
}
}
当然,只有在正确地将原则应用于设计时,才可能使用装饰器,因为您通常需要有一些明确的泛型抽象,以便能够将装饰器应用于系统中的大量类。在遗留代码库中高效地使用decorator可能会让我望而生畏。这在多线程应用程序中应该可以正常工作,因为每个线程都应该有自己的对象图。所以,当您开始处理某个任务时,您首先要解析一个新的图形,并且图形不应该从一个线程传递到另一个线程。这允许将什么是线程安全(什么不是)的知识集中到应用程序中连接所有内容的一个地方:线程 当您这样工作时,这意味着当您使用此拦截器来监视单例类(以及跨线程使用的类)时,每个线程仍将获得自己的拦截器(当其注册为瞬态时),因为每次解析时,您都会获得一个新的拦截器(即使您重用相同的“拦截器”实例) 然而,这确实意味着您必须非常小心地将这个被拦截的组件注入到其中,因为如果您将这个被拦截的对象注入到另一个单例中,您将再次遇到麻烦。这种特殊的“麻烦”被称为生活方式不匹配。这很容易让你不小心误解了你的容器,从而给自己带来麻烦,不幸的是Ninject没有可能警告你这一点 但请注意,如果您开始使用decorator而不是拦截器,您的问题将消失,因为使用decorator,您可以将所有内容保存在一个方法中。这意味着即使decorator也可以是单实例,而不会引起任何线程问题。例如:
//命令处理程序的时间交叉关注点
公共类TimingCommandHandlerDecorator:ICommandHandler
{
私有只读ICommandHandler装饰对象;
公共计时CommandHandlerDecorator(ICommandHandler decoratee)
{
this.decoree=decoree;
}
公共无效句柄(TCommand命令)
{
var stopwatch=stopwatch.StartNew();
this.decoree.Handle(命令);
Debug.WriteLine(秒表已过);
}
}
当然,只有在正确地将原则应用于设计时,才可能使用装饰器,因为您通常需要有一些明确的泛型抽象,以便能够将装饰器应用于系统中的大量类。在遗留代码库中高效地使用decorator可能会让我望而生畏。这在多线程应用程序中应该可以正常工作,因为每个线程都应该有自己的对象图。所以,当您开始处理某个任务时,您首先要解析一个新的图形,并且图形不应该从一个线程传递到另一个线程。这允许将什么是线程安全(什么不是)的知识集中到应用程序中连接所有内容的一个地方:线程 当您这样工作时,这意味着当您使用此拦截器来监视单例类(以及跨线程使用的类)时,每个线程仍将获得自己的拦截器(当其注册为瞬态时),因为每次解析时,您都会获得一个新的拦截器(即使您重用相同的“拦截器”实例) 然而,这确实意味着您必须非常小心地将这个被拦截的组件注入到何处,因为如果您将这个被拦截的对象注入到另一个对象中