Asp.Net Core - 需要从没有依赖注入的情况下生成的实例访问HttpContext实例

时间:2016-03-17 00:54:53

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

我正在使用Asp.Net Core RC1,并且我已经从模型生成器(来自HttpContext的拦截器)生成的实例访问Castle.Core实例,精确)。模型生成器必须是整个应用程序的单个实例。

我需要在启动文件中创建ModelGenerator的实例,因为它用于配置某些序列化程序所需的静态lambda。序列化程序是静态注册的,所以我必须写入启动:

var modelGenerator = new ModelGenerator();
Serializers.Configure(modelGenerator); // static use of model generator instance

我还将modelGenerator添加为用于DI的其他用途的单例实例。

services.AddInstance<IModelGenerator>(modelGenerator);

我对DI所做的是从ModelGenerator的构造函数中获取IHttpContextAccessor接口,但在此上下文中我不能因为我在启动时没有实例。我需要类似ServiceLocator的东西从ModelGenerator调用,或者我忽略的其他一些模式。

如何从ModelGenerator生成的拦截器中获取更新的HttpContext实例以及当前请求的信息?

1 个答案:

答案 0 :(得分:3)

似乎无法在应用程序启动时获取HttpContext的实例。这是有道理的 - 在以前版本的MVC中,这在IIS集成模式或OWIN中是不可能的。

所以你有两个问题:

  • 如何将IHttpContextAccessor引入序列化程序?
  • 如何确保HttpContext在可用之前无法访问?

第一个问题非常简单。您只需要在IHttpContextAccessor上使用构造函数注入。

public interface ISerializer
{
    void Test();
}

public class ModelGenerator : ISerializer
{
    private readonly IHttpContextAccessor httpContextAccessor;

    public ModelGenerator(IHttpContextAccessor httpContextAccessor)
    {
        this.httpContextAccessor = httpContextAccessor;
    }

    public void Test()
    {
        var context = this.httpContextAccessor.HttpContext;

        // Use the context
    }
}

注册......

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // Other code...

    // Add the model generator
    services.AddTransient<ISerializer, ModelGenerator>();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    var serializers = app.ApplicationServices.GetServices<ISerializer>();
    foreach (var serializer in serializers)
    {
        Serializers.Configure(serializer);
    }

    // Other code...
}

第二个问题可以通过将您需要HttpContext的任何初始化调用移入全局过滤器来解决。

public class SerializerFilter : IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext context)
    {
        // TODO: Put some kind of if condition (possibly a 
        // global static variable) here to ensure this 
        // only runs when needed.
        Serializers.Test();
    }
}

并全局注册过滤器:

public void ConfigureServices(IServiceCollection services)
{
    // Other code...

    // Add the global filter for the serializer
    services.AddMvc(options =>
    {
        options.Filters.Add(new SerializerFilter());
    });

    // Other code...
}

如果您的Serializers.Configure()方法需要HttpContext才能生效,那么您需要将该调用移至全局过滤器中。

相关问题