asp.net核心中的依赖注入

时间:2017-08-08 14:10:02

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

我有以下代码:

public void ConfigureServices(IServiceCollection services)
    {
      ...
      services.AddScoped<IWsApiProvider, WsApiProvider>();
      services.AddScoped<IApplicationUserRepository, ApplicationUserRepository>();
      ...
    }

WsApiProvider有以下内容:

public Guid SessionId { get; set; }
public IWSocketProvider WsApi { get; set; }

在Invoke方法中,我正在更新这些属性:

public Task Invoke(HttpContext httpContext, IOptions<AppSettings> appSettings)
    {
      ...
      this._wsApiProvider.SessionId = sessionGuid;
      this._wsApiProvider.WsApi = connection;
      ...
    }

然后我要去Controller,我注入了Repository:

public AccountController(IApplicationUserRepository applicationUserRepository)
    {
        this._applicationUserRepository = applicationUserRepository;
    }

    public ApplicationUserRepository(IWsApiProvider wsApi) : base(wsApi)
    { 
    }

这里我有wsApi对象,空属性。两个问题:

  1. 为什么在存储库构造函数中我有这个具有空属性的对象?

  2. 有没有办法为每个请求(非单一解决方案)的所有依赖项创建一个IWsApiProvider实例?

  3. 提前谢谢

    更新。整个中间件类:

    public class WsApiMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IWsApiProvider _wsApiProvider;
        private const string QisSessionId = "QisSessionId";
    
        public WsApiMiddleware(RequestDelegate next, IWsApiProvider wsApiProvider)
        {
            _next = next;
            this._wsApiProvider = wsApiProvider;
        }
    
    
        public Task Invoke(HttpContext httpContext, IOptions<AppSettings> appSettings)
        {
            var sessionId = httpContext.Request.Cookies[QisSessionId];
            var sessionGuid = Guid.Empty;
    
            if (!string.IsNullOrEmpty(sessionId))
            {
                Guid.TryParse(sessionId, out sessionGuid);
            }
    
            var connection = ConnectionsPool.GetSocket(sessionGuid);
    
            if (connection == null)
            {
                connection = new WSocketProvider(null);
    
                var connectTask = Task.Run(async () =>
                await connection.Connect(appSettings.Value.WsApiServerEndPointUri, CancellationToken.None)
                );
    
                Task.WaitAll(connectTask);
    
                var sessionService = new SessionService(connection);
    
                var sessionOpenTask = Task.Run(async () =>
                {
                    SessionDataState sessionData = null;
    
                    //TODO [W-8/6/2017] - think about better solution for situation when sessionId doesn't exist on the server
                    try
                    {
                        sessionData = await sessionService.OpenSession(sessionGuid != Guid.Empty ? (Guid?)sessionGuid : null);
                    }
                    catch (Exception ex)
                    {
                        sessionData = await sessionService.OpenSession();
                    }
    
                    sessionGuid = sessionData.SessionId;
    
                    if (!sessionData.ClientType.HasValue)
                    {
                        await sessionService.LoginClient();
                    }
    
                    ConnectionsPool.TryAddConnection(sessionGuid, connection);
                    httpContext.Response.Cookies.Append(QisSessionId, sessionGuid.ToString());
                });
    
                Task.WaitAll(sessionOpenTask);
            }
    
            this._wsApiProvider.SessionId = sessionGuid;
            this._wsApiProvider.WsApi = connection;
    
            return this._next(httpContext);
        }
    }
    
    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class WsApiMiddlewareExtensions
    {
        public static IApplicationBuilder UseWsApiMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<WsApiMiddleware>();
        }
    }
    

2 个答案:

答案 0 :(得分:3)

来自ASP.Net core middleware doc

  

每个应用程序生命周期构建一次。由于中间件是在应用程序启动时构建的,而不是按请求构建的,因此中间件构造函数使用的作用域生存期服务在每个请求期间不会与其他依赖注入的类型共享。

在你的情况中最重要的部分:

  

如果必须在中间件和其他类型之间共享作用域服务,请将这些服务添加到:rose方法的签名中。 PREFIX : <http://example.com/> CONSTRUCT { ?s ?p ?o . } WHERE { SELECT ?s ?p ?o WHERE { { ?s ?p ?o } MINUS { :rose ?p ?o ; rdf:type ?c . ?c rdfs:subClassOf ?super . ?s ?p ?x1 . ?x2 ?x3 ?o } } } 方法可以接受依赖注入填充的其他参数。

由于Invoke是作用域服务(即每个请求),因此应将其作为参数传递给Invoke方法,如下所示:

Invoke

答案 1 :(得分:0)

问:为什么在存储库构造函数中我有这个具有空属性的对象?

答:我最好的猜测是你的中间件存在问题。 我猜你因为Invoke方法而使用中间件。例如。您可能在处理HttpContext后设置属性值,而不是之前。 这是 猜测,因为代码示例不完整。

问:有没有办法为每个请求(非单一解决方案)的所有依赖项创建一个IWsApiProvider实例?

答:是的,您使用AddScoped即可,就像您已经在做的那样(并按照official docs中的说明):

  

每个请求都会创建一次范围生命周期服务。

     

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection#service-lifetimes-and-registration-options

我的建议:发布更多代码,有人可能会帮助您。