我有一个Nancy模块和一个decorator类,需要知道ClaimsPrincipal才能检索用户的电子邮件地址。所以我声明了一个构造函数为

public EmailDecorator(IDbConnectionFactory connectionFactory,
                      IPrincipal principal,
                      IEmailClient emailClient) : base(connectionFactory)


我正在努力弄清楚的是如何将主体注入到构造函数中。我正在使用用于DI的Simple Injector,它非常有效。但是,如果我重写了作为NancyContext参数的ConfigureRequestContainer()方法来实例化IPrincipal,则会出现异常

protected override void ConfigureRequestContainer(
    TinyIoCContainer container, NancyContext context)
{
    container.Register<IPrincipal>((c, o) => context.CurrentUser);
    base.ConfigureRequestContainer(container, context);
}


异常表示Simple Injector不知道默认TinyIOC容器中注册的IPrincipal


  配置无效。为InvoiceModule类型创建实例失败。类型为EmailDecorator的构造函数包含名称为“ principal”的参数和类型为IPrincipal的未注册参数。请确保已注册IPrincipal,或更改EmailDecorator的构造函数。


编辑

我花了很长时间尝试解决此问题,我怀疑答案是停止尝试以这种方式进行。在我的原始示例中,我试图将IPrincipal注入到装饰器构造函数中,这是不正确的。相反,我需要注入某种形式的服务,允许在装饰器中的一种方法被调用时派生IPrincipal,例如Func<IPrincipal>。 Nancy提供了一个可覆盖的方法ConfigureRequestContainer(),该方法将为每个请求调用,因此有可能被使用:

protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
{
    container.Register<Func<IPrincipal>>((c, o) =>
    {
        return () => context.CurrentUser;
    });
}


除了请求容器是TinyIoCContainer,而且我正在使用SimpleInjector。因此,也许我可以添加一个SimpleInjector注册,从而将解析卸载到请求容器中?

_container.RegisterSingleton<Func<IPrincipal>>(() => nancy.Resolve<Func<IPrincipal>>());


实际上,nancy与请求容器不是同一容器。因此,也许某个地方有一个可以成功解析IPrincipal的容器,但我不知道如何访问它。练习的目的是避免必须修改回购代码的方法签名以包括ClaimsPrincipal,就像过去可以调用Thread.CurrentPrincipal的过去一样。仍在寻找线索,但将开始修改方法签名以包括ClaimsPrincipal。

最佳答案

答案是使用IHttpContextAccessor。在Startup.cs中,在ConfigureServices()方法中添加一个新的服务定义:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IAppSettings>(settings);
    services.AddSingleton<IHttpContextAccessor>(new HttpContextAccessor());
    …
 }


然后将app.ApplicationServices作为参数传递给引导程序:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAppSettings settings)
{
    var log = ConfigureLogger(settings);
    app.UseOwin(buildFunc =>
    {
        buildFunc.UseMonitoringAndLogging(log, HealthCheckAsync);
        buildFunc.UseNancy(cfg =>
            cfg.Bootstrapper = new Bootstrapper(env, log, app.ApplicationServices));
    });
}


在Bootstrapper类ApplicationStartup()方法中,在Simple Injector容器中注册服务:

    public Bootstrapper(IHostingEnvironment env, ILogger log, IServiceProvider services)
    {
        _env = env;
        _log = log;
        _services = services;
    }

    …

    _container.Register<IHttpContextAccessor>(() =>
        (IHttpContextAccessor) _services.GetService(typeof(IHttpContextAccessor)));


然后在装饰器类中,将IHttpContextAccessor添加到构造器中:

public EmailDecorator(IDbConnectionFactory connectionFactory,
                      ILogger log,
                      IHttpContextAccessor httpContextAccessor,
                      IEmailClient emailClient) : base(connectionFactory, log)
{
    _emailClient = emailClient;
    _httpContextAccessor = httpContextAccessor;
}


可以从_httpContextAccessor.HttpContext属性访问ClaimsPrincipal

关于c# - 如何在南希注入(inject)ClaimsPrincipal,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47585008/

10-11 15:21