C# 从.NETCore2.1中的单例服务注入作用域服务

C# 从.NETCore2.1中的单例服务注入作用域服务,c#,asp.net-web-api,asp.net-core,.net-core,C#,Asp.net Web Api,Asp.net Core,.net Core,我有一个助手。当我使用“AddScoped”将CacheHelper的依赖项添加到启动时,它正在工作。但是,CacheHelper.cs正在为每个请求运行。所以,我转换为“AddSingleton”,如下所示。但我犯了一个错误,比如: 无法使用singleton“MyProject.Caching.iCache Helper”中的作用域服务“MyProject.DataAccess.IUnitOfWork”如何解决此问题 Strartup.cs public void ConfigureServ

我有一个助手。当我使用“AddScoped”将CacheHelper的依赖项添加到启动时,它正在工作。但是,
CacheHelper.cs
正在为每个请求运行。所以,我转换为“AddSingleton”,如下所示。但我犯了一个错误,比如: 无法使用singleton“MyProject.Caching.iCache Helper”中的作用域服务“MyProject.DataAccess.IUnitOfWork”如何解决此问题

Strartup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();
        services.AddScoped<IUnitOfWork, UnitOfWork>();
        services.AddScoped<IJwtHelper, JwtHelper>();
        services.AddScoped<IAuditHelper, AuditHelper>();
        services.TryAdd(ServiceDescriptor.Singleton<IMemoryCache, MemoryCache>());
        services.AddSingleton<ICacheHelper, CacheHelper>();
        services.AddMvc();

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    }
public void配置服务(IServiceCollection服务)
{
AddHttpContextAccessor();
services.addScope();
services.addScope();
services.addScope();
services.TryAdd(servicescriptor.Singleton());
services.AddSingleton();
services.AddMvc();
services.AddSingleton();
}
CacheHelper.cs

public class CacheHelper : ICacheHelper
{
    private readonly IUnitOfWork unitOfWork;
    public IMemoryCache Cache { get; }

    public CacheHelper(IUnitOfWork unitOfWork, IMemoryCache cache)
    {
        this.unitOfWork = unitOfWork;
        Cache = cache;
    }

    public void SetCommonCacheItems()
    {
        var cities = unitOfWork.CityRepo.GetAll();
        Cache.Set("cities", cities);

        string obj;
        Cache.TryGetValue<string>("cities", out obj);
    }

    public string GetCities()
    {
        string obj;
        Cache.TryGetValue<string>("cities", out obj);

        return obj;
    }
}
公共类CacheHelper:ICacheHelper
{
私有只读IUnitOfWork;
公共IMemoryCache缓存{get;}
公共CacheHelper(IUnitOfWork、IMemoryCache缓存)
{
this.unitOfWork=unitOfWork;
缓存=缓存;
}
public void SetCommonCacheItems()
{
var cities=unitOfWork.CityRepo.GetAll();
Cache.Set(“城市”,cities);
字符串对象;
Cache.TryGetValue(“城市”,输出对象);
}
公共字符串GetCities()
{
字符串对象;
Cache.TryGetValue(“城市”,输出对象);
返回obj;
}
}

您以前的方式是正确的<代码>ICacheHelper应该而且必须确定范围

只是缓存实现是错误的。获取城市将被调用,它将检查缓存。如果找不到,它将获取数据并将其放入缓存

public class CacheHelper : ICacheHelper
{
    private readonly IUnitOfWork unitOfWork;
    public IMemoryCache Cache { get; }

    public CacheHelper(IUnitOfWork unitOfWork, IMemoryCache cache)
    {
        this.unitOfWork = unitOfWork;
        Cache = cache;
    }

    public string GetCities()
    {
        if(!Cache.TryGetValue<string>("cities", string out cities))
        {
            // not found in cache, obtain it
            cities = unitOfWork.CityRepo.GetAll();
            Cache.Set("cities", cities);
        }

        return cities;
    }
}
公共类CacheHelper:ICacheHelper
{
私有只读IUnitOfWork;
公共IMemoryCache缓存{get;}
公共CacheHelper(IUnitOfWork、IMemoryCache缓存)
{
this.unitOfWork=unitOfWork;
缓存=缓存;
}
公共字符串GetCities()
{
如果(!Cache.TryGetValue(“cities”,串出cities))
{
//在缓存中找不到,请获取它
cities=unitOfWork.CityRepo.GetAll();
Cache.Set(“城市”,cities);
}
回归城市;
}
}

您不需要
SetCommonCacheItems()
方法。重要的是,
IMemoryCache
是静态的,因为它将包含数据。由于数据库的原因,UoW必须具有作用域,否则会出现内存泄漏(特别是在使用EF Core时,因为它缓存/跟踪实体)。

值得您花时间阅读:单例不能引用作用域InstanceHanks@JohnB。我现在读了你的帖子。在那个帖子中,它建议我将unitOfWork添加为singleton。但当我以单例的形式执行UnitOfWork时,我的请求并没有进入服务器。哪里会出错?非常感谢@Tseng。在我看来,所有内容都必须是单例的,否则请求将变得越来越慢。所以,我试过单身汉。但我从您的回复中了解到,每个服务都有其作用域并没有任何缺点。这是真的吗?通常情况下,作用域是理想的方式,因为否则长期存在的服务将/可能保留未释放的内存,并且您的应用程序将继续使用越来越多的内存,直到崩溃。类和它们的构造函数应该是快速的,如果你在构造函数中做了一些需要大量工作的事情,那么你就错了。再次感谢@Tseng。这对我来说是很有用的信息。重点是,由于EF Core和其他东西的工作方式,您的UoW必须被限定范围,所以您不需要保存任何东西,也不需要通过将其设置为单例来帮自己的忙。IMemoryCache无论如何都是静态的。因此,当
CacheHelper
被构造时,只有UoW实例(如果尚未为该请求进行实例化并传入的话)。
cachelper
构造函数只对其进行赋值,因此其速度非常快且IMemory缓存已经存在,因此只传递其引用