3

我讀了這些(+,+,++)頁面,但我無法弄清楚我該怎麼做。Web API自我託管應用程序和簡單噴油器中的LifetimeScoping錯誤

我有這個簡單的界面和具體類型:

public interface IIdentifierGenerator { 
    long Generate(Type type); 
    long Generate<TType>(TType type); 
} 
public HiloIdentifierGenerator : IIdentifierGenerator { /* implementation... */ } 

我創建這個DependencyResolver

public class SelfHostedSimpleInjectorWebApiDependencyResolver : IDependencyResolver { 
    private readonly Container _container; 
    private readonly LifetimeScope _lifetimeScope; 

    public SelfHostedSimpleInjectorWebApiDependencyResolver(
     Container container) 
     : this(container, false) { 
    } 

    private SelfHostedSimpleInjectorWebApiDependencyResolver(
     Container container, bool createScope) { 
     _container = container; 

     if (createScope) 
      _lifetimeScope = container.BeginLifetimeScope(); 
    } 

    public IDependencyScope BeginScope() { 
     return new SelfHostedSimpleInjectorWebApiDependencyResolver(
      _container, true); 
    } 

    public object GetService(Type serviceType) { 
     return ((IServiceProvider)_container).GetService(serviceType); 
    } 

    public IEnumerable<object> GetServices(Type serviceType) { 
     return _container.GetAllInstances(serviceType); 
    } 

    public void Dispose() { 
     if (_lifetimeScope != null) 
      _lifetimeScope.Dispose(); 
    } 
} 

和我配置我的服務器是這樣的:

_config = new HttpSelfHostConfiguration("http://192.168.1.100:20000"); 
_config.Routes.MapHttpRoute(
    "API Default", "api/{controller}/{id}", 
    new { id = RouteParameter.Optional }); 
_config.DependencyResolver = 
    new SelfHostedSimpleInjectorWebApiDependencyResolver(
     IoC.Wrapper.GetService<Container>()); 
_server = new HttpSelfHostServer(_config); 
/* etc. */ 

這是我的控制器:

public class IdentifierController : ApiController { 

    private readonly IIdentifierGenerator _identifierGenerator; 

    public IdentifierController(IIdentifierGenerator identifierGenerator) { 
     _identifierGenerator = identifierGenerator; 
    } 

    public long Get(string id) { 
     var type = Type.GetType(id, false, true); 
     return type == null ? -1 : _identifierGenerator.GetIdentifier(type); 
    } 
} 

現在,當我打電話的操作方法,我得到這個錯誤:

It is not safe to use a LifetimeScope instance across threads. Make sure the complete operation that the lifetime scope surrounds gets executed within the same thread and make sure that the LifetimeScope instance gets disposed on the same thread as it gets created. Dispose was called on thread with ManagedThreadId 28, but was created on thread with id 29.

我在哪裏做錯了嗎?你能幫忙嗎?

回答

2

Simple Injector中的Lifetime Scope生活方式旨在用於單線程。在多個線程上運行它(甚至調用Dispose)不是線程安全的。但是,Web API自託管會將創建的作用域放置在不同的線程中,甚至可以安排控制器在與創建生命週期作用域不同的線程上運行。由於這是不安全的,所以在這種情況下簡單注射器會引發異常。

正如我在this討論解釋,我不知道在Web API級很好的解決,但遷移到一個基於消息的架構的時候,這個問題完全消失,因爲你可以在控制器中注入的ICommandHandler<TCommand>並用修飾器來修飾該控制器,該修飾器將生命週期範圍行爲添加到命令處理程序中。這樣你應該用一個更簡單的解析器代替你的SelfHostedSimpleInjectorWebApiDependencyResolver,它不會創建一個生命週期範圍。我在討論中解釋了它,並提到了其他SO答案和博客文章。我知道你已經閱讀過這篇文章,因爲你已經提到了答案,但這是我能給你的最好的答案。

+0

嘿親愛的@Steven。感謝回答。但我認爲將所有東西都轉移到基於消息的架構並不是一個好的解決方案,有時候這不僅是可能的。但是,我創建了一些'IDependencyResolver'和'IDependencyScope' [here]的簡單實現(https://gist.github.com/kavand/5610025)。你會看看他們,說他們有什麼問題嗎?我測試主題,看起來他們工作。但是,由於我真的是一個新的Web API編碼器,我不能確定我的工作是否正確。我在等你的意見。非常感謝簡單的注射器。很可愛。 –

+0

@Javad_Amiry:你的實現不起作用。不要像現在在'SiWebApiDependencyResolver'中那樣爲應用程序的生命週期(全局)創建生命週期範圍。處理'SiWebApiDependencyScope'時不要手動處理對象。生命週期範圍已經這樣做,你可能會調用多次在同一個對象上處理。除非需要非託管資源,否則不要在類上實現終結器。 – Steven

+0

如果基於消息的體系結構不適合您並且使用IIS託管的Web API不是一個選項,那麼使用簡單注入器目前可能不是您的最佳策略。 – Steven

相關問題