【问题标题】:HttpContextAccessor, IPrincipal and ServiceCollectionHttpContextAccessor、IPrincipal 和 ServiceCollection
【发布时间】:2016-04-27 16:14:44
【问题描述】:

有没有办法实现下一个行为?

public static void Configure(IServiceCollection services) {
    services.AddScoped(typeof(Func<IPrincipal>), ???);
    services.AddInstance(typeof(Func<IPrincipal>), ???);
}

1.不起作用:

Func<IServiceProvider, IPrincipal> getPrincipal = 
    (sp) => sp.GetService<IHttpContextAccessor>().HttpContext.User;

services.AddScoped(
    typeof(Func<IPrincipal>), 
    getPrincipal);  

2.不起作用:

var builder = services.BuildServiceProvider();

services.AddInstance(
    typeof(Func<IPrincipal>),
    builder.GetService<IHttpContextAccessor>().HttpContext.User);

【问题讨论】:

  • 你想达到什么目的?目前尚不清楚您需要什么最终结果。例如,您是否想要一个返回当前用户的服务?

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


【解决方案1】:
Func<IServiceProvider, IPrincipal> getPrincipal = 
    (sp) => sp.GetService<IHttpContextAccessor>().HttpContext.User;

services.AddScoped(
    typeof(Func<IPrincipal>), 
    getPrincipal); 

您正在尝试解析委托,但我假设您想要解析 IPrincipal。我假设您的服务可能看起来像这样

public class MyService : IMyService 
{
    public MyService(IPrincipal principal) 
    {
        ...
    }
}

如果是这样,那么您的注册是错误的。您正在注册 Func&lt;IPrincipal&gt;,但期待未注册的 IPrincipal。

您应该为IPrincipal 注册工厂或(不太推荐恕我直言)将Func&lt;IPrincipal&gt; 注入您的服务。

Func<IServiceProvider, IPrincipal> getPrincipal = 
    (sp) => sp.GetService<IHttpContextAccessor>().HttpContext.User;

services.AddScoped<IPrincipal>(getPrincipal); 

或更短的

services.AddScoped<IPrincipal>(
    (sp) => sp.GetService<IHttpContextAccessor>().HttpContext.User
); 

或

public class MyService : IMyService 
{
    priate IPrincipal principal;
    public MyService(Func<IPrincipal> principalFactory) 
    {
        this.principal = principalFactory();
    }
}

【讨论】:

    【解决方案2】:

    工作解决方案:

    Func<IServiceProvider, IPrincipal> getPrincipal = 
        (sp) => sp.GetService<IHttpContextAccessor>().HttpContext.User;
    
    services.AddScoped(typeof(Func<IPrincipal>), sp => {
        Func<IPrincipal> func = () => {
            return getPrincipal(sp);
        };
    
        return func;
    });
    

    【讨论】:

    • 您不需要将其包裹在委托周围。 AddScoped 有两个重载。一种可以传入具体类型,另一种可以传入工厂方法。使用工厂重载时,每次需要实例化类型时都会调用工厂。或者有什么特殊原因需要它作为代表?
    • 在我当前的任务中,我必须在构造函数中注入 Func&lt;IPrincipal&gt; 作为参数
    猜你喜欢
    • 2023-02-21
    • 2023-04-08
    • 1970-01-01
    • 2018-01-26
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    相关资源
    最近更新 更多