2016-06-28 34 views
0

在.NET中的API控制器项目中,我使用的服务(如SomeService)只需要一次初始化(不是每个请求或每个SomeService实例)(虽然我不认为它是相关的,但这里的解释这个初始化部分:它在Azure存储一些设置一次的API创建做这行的SomeService每个实例是unnecessarely成本因此有下面一行在Global.asax中Autofac - 从DependencyResolver.Current.GetService创建的InstancePerRequest <>() - 何时发布?

new SomeService().Init(); 

现在,我使用Autofac进行依赖注入。我注册SomeServiceISomeServiceInstancePerRequest(因为SomeService不是线程安全的)。因此现在我想初始化SomeSer Global.asax中的副本通过容器中的实例。但是如果我试图从容器实例作为

container.Resolve<ISomeService>().Init(); 

它给这个错误

An exception of type 'Autofac.Core.DependencyResolutionException' occurred in Autofac.dll but was not handled in user code 

Additional information: No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself. 

因此在Global.asax中,我得到一个实例作为错误解释建议。

DependencyResolver.Current.GetService<ISomeService>().Init(); 

我想知道的是,SomeService比如我从Current得到释放或没有?由于没有真正的要求,我不确定。在最坏的情况下,我可以通过new从混凝土中获得实例。

回答

1

您正在尝试将2个职责合并为1个组件,该组件打破Single Responsibility Principle

为了解决这个问题,您可以将组件分割为一个将初始化天蓝色存储的组件(例如IStorageProvider)和另一个将完成这项工作的组件。 IStorageProvider将被声明为SingleInstance(如果需要,则执行IStartable),另一个组件将使用此组件。

public class AzureStorageProvider : IStorageProvider, IStartable 
{ 
    public void Start() 
    { 
     // initialize storage 
     this._storage = new ... 
    } 
} 


public class SomeService : ISomeService 
{ 
    public SomeService(IStorageProvider storageProvider) 
    { 
     this._storageProvider = storageProvider; 
    } 

    private readonly IStorageProvider _storageProvider; 

    public void Do() 
    { 
     // do things with storage 
     this._storageProvider.Storage.ExecuteX(); 
    } 
} 

和登记:

builder.RegisterType<AzureStorageProvider>().As<IStorageProvider>().SingleInstance(); 
builder.RegisterType<SomeService>().As<ISomeService>().InstancePerRequest(); 

你也可以注册一个IStorage,让SomeService直接取决于IStorage并使用IStorageProvider作为工厂。

builder.Register(c => c.Resolve<IStorageProvider>().Storage).As<IStorage>(); 
+0

你有一些好点。 IStartable似乎是一个很好的解决方案,但是我不想将与特定容器(如IStartable)相关的任何内容添加到包含服务的dll。有些可以使用Autofac,有些使用别的。另外,如果我为初始化目的构建另一个服务并将其注册为单例,它的实例也不会被释放。我更同意这本书。然而在实践中没有任何改变。我对吗? –

+0

如果您将初始化程序注册为单例,则在应用程序停止时将处理实例。但我不认为这是一个真正的问题,因为你不需要处理它,据我所知,你只需要处理'SomeService' –

相关问题