在.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
来获取具体的实例。
答案 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>();