Autofac - 从DependencyResolver.Current.GetService<>()创建的InstancePerRequest - 什么时候发布?

时间:2016-06-28 13:54:41

标签: c# asp.net-mvc autofac dependency-resolver

在.NET中的API控制器项目中,有一个我正在使用的服务,比如SomeService,只需要一次初始化(不是每个请求或每个SomeService实例)(尽管我不认为它是相关的,这里是对这个初始化部分的解释:它在Azure存储中进行了一些设置,一旦创建了api。为SomeService的每个实例执行此操作是不必要的代价。因此,Global.asax中有以下行

new SomeService().Init();

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

中获取容器中的实例
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 个答案:

答案 0 :(得分:1)

您正在尝试将2个职责合并为1个组件,这些组件会破坏Single Responsibility Principle

为了解决这个问题,您可以使用将初始化azure存储(例如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>();