在.NET中的API控制器项目中,我正在使用的服务,例如SomeService
,仅需要一次初始化(不是每个请求或每个someService实例)(尽管我没有)认为这是相关的,这里对此一部分的解释:它在创建API时在Azure存储中进行一些设置。对于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();
我想知道的是,我从Current
获得的SomeService
实例是发布的吗?由于没有真正的请求,我不确定。在最糟糕的情况下,我可以使用new
的混凝土获得实例。
您正在尝试将2个职责合并为1个组件,这些责任破坏了单一责任原则。
为了解决它,您可以使用将初始化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>();