1

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

new SomeService().Init();

现在,我正在使用Autofac依赖注入。我注册SomeServiceISomeService和注册为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.

4

1 回答 1

1

您正在尝试将 2 个职责合并为 1 个组件,这违反了单一职责原则

为了解决它,您可以将组件拆分为一个将初始化天蓝色存储(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 直接依赖IStorageIStorageProvider作为工厂使用。

builder.Register(c => c.Resolve<IStorageProvider>().Storage).As<IStorage>(); 
于 2016-06-29T10:32:17.347 回答