【问题标题】:Dependency injection in asp.net coreasp.net core 中的依赖注入
【发布时间】:2018-01-16 03:51:48
【问题描述】:

我有以下代码:

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;
      ...
    }

然后我将前往注入 Repository 的 Controller:

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

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

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

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

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

提前谢谢你

已更新。整个中间件类:

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>();
    }
}

【问题讨论】:

  • Invoke 方法从何而来? _wsApiProvider 是什么?
  • Invoke 方法来自MiddleWare.cs,在startup:app.UseWsApiMiddleware(); IWsApiProvider 是一个简单的接口,有两个属性: public Guid SessionId { get;放; } 公共 IWSocketProvider WsApi { 获取;放; }
  • 你将IWSocketProvider 作为参数传递给Middleware.cs,还是在那里构建?
  • 是的,我将它作为构造函数参数传递:public WsApiMiddleware(RequestDelegate next, IWsApiProvider wsApiProvider)
  • 发布更多代码;特别是中间件会很有趣。

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


【解决方案1】:

来自ASP.Net core middleware doc

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

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

如果您必须在中间件和其他类型之间共享范围服务,请将这些服务添加到 Invoke 方法的签名中。 Invoke 方法可以接受由依赖注入填充的附加参数。

由于IWsApiProvider 是一个范围服务(即每个请求),它应该作为参数传递给 Invoke 方法,如下所示:

public class WsApiMiddleware
{
    private readonly RequestDelegate _next;

    // no longer passed in the constructor
    public WsApiMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    // passed as an argument to Invoke, via dependency injection
    public Task Invoke(HttpContext httpContext, IWsApiProvider wsApiProvider, IOptions<AppSettings> appSettings)
    {
        wsApiProvider.SessionId = "SessionId";
        wsApiProvider.WsApi = "WsApi";

        return this._next(httpContext);
    }
}

【讨论】:

    猜你喜欢
    • 2019-02-22
    • 1970-01-01
    • 1970-01-01
    • 2017-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多