【问题标题】:Is there a way to have Dependency Injection and an Extension method interact?有没有办法让依赖注入和扩展方法交互?
【发布时间】:2021-03-27 11:57:40
【问题描述】:

我的 NuGet 包库中有一个方法,如下所示:

public async Task<string> GetLogoutUrl(HttpContext httpContext, string encodedUserJwt, string relativeRedirectUrl)
{
    var redirectUrl = $"{httpContext.Request.Scheme}://{httpContext.Request.Host}/{relativeRedirectUrl}";
    var logoutUrlParameters = $"id_token_hint={encodedUserJwt}&post_logout_redirect_uri={redirectUrl}";
    var logoutUrl = $"{await DiscoveryDocument.GetLogoutEndpoint()}?{logoutUrlParameters}";
    return logoutUrl;
}

我真的很想把它变成HttpContext 的扩展方法,这样我的 NuGet 用户就可以这样称呼它:HttpContext.GetLogoutUrl(encodedUserJwt, "Home");

但是问题在于这个方法使用了DiscoveryDocument,它被注入到这个方法当前所在的类中。我一直在想一种方法,我可以获得扩展方法的良好语法,但仍然能够从依赖注入中获得DiscoveryDocument,同时又不会破坏那么多我晚上睡不着的最佳实践。

在 C# 中有没有办法拥有扩展方法并仍然连接到依赖注入对象?

注意:我不想让使用我的 NuGet 的开发人员必须传入 DiscoveryDocument 的实例。对于我的 NuGet 架构来说,这比仅仅让 GetLogoutUrl 不是扩展方法更糟糕。

【问题讨论】:

  • 扩展方法 -> 静态类 -> 无 DI :)
  • 为什么需要它作为参数? DiscoveryDocument 实际上是该方法的输入,即使它是隐式的 this.。这是一个依赖。
  • @madreflection - 虽然是公开的,但它比我希望我的用户必须与之交互的层次更深。正如我所说,最好将它保留在它所在的班级中。(它所在的班级处于“中等”级别,而DiscoveryDocument处于“低”级别。)

标签: c# asp.net-core dependency-injection extension-methods


【解决方案1】:

服务定位器通过

IServiceProvider HttpContext.RequestServices { get }

必须使用,因为这是一个静态调用,它通常不能很好地与 DI 配合使用,因为它通常以实例为中心。

潜在的扩展方法最终看起来像这样

public static async Task<string> GetLogoutUrl(this HttpContext httpContext, 
    string encodedUserJwt, string relativeRedirectUrl) {
    var redirectUrl = $"{httpContext.Request.Scheme}://{httpContext.Request.Host}/{relativeRedirectUrl}";
    var logoutUrlParameters = $"id_token_hint={encodedUserJwt}&post_logout_redirect_uri={redirectUrl}";

    var DiscoveryDocument = httpContext.RequestServices
        .GetRequiredService<DiscoveryDocumentTypeHere>();

    var logoutUrl = $"{await DiscoveryDocument.GetLogoutEndpoint()}?{logoutUrlParameters}";
    return logoutUrl;
}

【讨论】:

  • 感谢您的回答!我知道 Service Locator 是一种反模式,但是这与 DI 有什么关系呢? (如果我这样做,我需要知道我的 DI 系统中可能会出现什么问题。)
  • 无,前提是您是在组合根目录中注册已知类型的人。我假设您的 Nuget 有一些配置扩展,可以添加所有必要的依赖项。
  • 我的 NuGet 确实添加了依赖项。我曾考虑使用单例进行依赖注入,然后从静态扩展方法访问单例。我认为这更清洁。尽管仍在使用反模式,但我认为这种权衡可能是值得的。谢谢你的回答!
  • 此范围内的反模式是实现需要注册和配置 DI 类型以使其可用性。在您提交此模式之前,请对您的扩展方法进行单元测试。
猜你喜欢
  • 2012-04-02
  • 2021-04-27
  • 2017-11-02
  • 2011-06-29
  • 2012-02-22
  • 2017-07-31
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多