【问题标题】:Unable to get Scoped Service in aspnetcore 1 - RC1 to work无法在 aspnetcore 1 中获得 Scoped Service - RC1 工作
【发布时间】:2016-02-19 20:21:26
【问题描述】:

当我尝试在同一请求中的 2 个中间件中访问它时,出于某种原因,我的作用域服务似乎正在生成同一类的不同实例。

场景:我正在添加这样的范围服务:

public interface ISimplyRecorder
    {
        void AddInfo(string key, string value);
        Dictionary<string, string> GetAllInfo();   
    }


public class SimplyCoreRecorderService : ISimplyRecorder
    {
        private Dictionary<string,string> data;

        public SimplyCoreRecorderService()
        {
            data = new Dictionary<string, string>();
        }

        public void AddInfo(string key,string value)
        {
            data.Add("",value);
        }

        public Dictionary<string,string> GetAllInfo()
        {
            return data;
        }

    }

然后是startup.cs中的以下内容

services.AddScoped<ISimplyRecorder,SimplyRecorderService>();

现在我在示例中间件的构造函数中调用此服务。我可以使用新实例访问服务并向其中添加数据,然后调用 await _next(context)。但是,当我在我的 HomeController 中调用服务时,MVC 遵循上面的中间件,我似乎得到了一个新的服务实例,即使它是同一个请求。

家庭控制器:

ISimplyRecorder _simply;
private IHostingEnvironment _env;

public HomeController(IHostingEnvironment env,ISimplyRecorder simply)
{
    _simply = simply;
    _env = env;
}

public IActionResult Index()
{
    _simply.AddInfo("Home:Action","resulted in index action");
    return View();
}

如果有人想试一试,请访问:https://github.com/muqeet-khan/SimplyCore 获取完整代码。

【问题讨论】:

    标签: asp.net-core asp.net-core-mvc


    【解决方案1】:

    中间件在第一次涉及时只被实例化一次,然后所有后续请求都由该中间件实例处理。不是每个请求的新中间件实例。

    您在中间件的构造函数中获得您的ISimplyRecorder,并将其“缓存”为私有只读变量。这意味着中间件将获取第一个请求的ISimplyRecorder 实例,然后继续为所有后续请求添加数据到该实例,而不是为您在HomeController 中获得的后续请求添加新的ISimplyRecorder 实例。

    要解决这个问题,需要从中间件的Invoke方法中获取ISimplyRecorder实例。

    // using Microsoft.Extensions.DependencyInjection;
    public async Task Invoke(HttpContext httpContext)
    {
        ISimplyRecorder recoder = httpContext.RequestServices.GetRequiredService<ISimplyRecorder>();
    }
    

    编辑:

    Juergen 的评论是正确的,我试了一下。你也可以这样写:

    public async Task Invoke(HttpContext httpContext, ISimplyRecorder recorder)
    {
        // recorder is from DI
    }
    

    【讨论】:

    • 如果我没记错的话,应该可以像这样注入 Invoke 方法:public async Task Invoke(HttpContext httpContext, ISimplyRecorder recoder )
    • 我会尽快尝试,但默认 DI 不是仅限于构造函数注入吗?
    • @Ma_Khan 不是真的。例如StartUp类中的Configure方法、中间件的Invoke方法以及Controller(HomeController)的action方法中的参数使用[FromService]属性
    • 测试成功...谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多