• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
PowerCoder
博客园    首页    新随笔    联系   管理    订阅  订阅

如何传递参数给ASP.NET Core的中间件(Middleware)

问题描述


当我们在ASP.NET Core中定义和使用中间件(Middleware)的时候,有什么好的办法可以给中间件传参数吗?

 

 

解决方案


 

在ASP.NET Core项目中添加一个POCO类来传递参数到中间件,例如下面的GreetingOptions类

public class GreetingOptions
{
    public string GreetAt { get; set; }
    public string GreetTo { get; set; }
}

然后添加一个中间件GreetingMiddleware

public class GreetingMiddleware
{
    private readonly RequestDelegate next;
    private readonly GreetingOptions options;

    public GreetingMiddleware(
        RequestDelegate next,
        GreetingOptions options)
    {
        this.next = next;
        this.options = options;
    }

    public async Task Invoke(
        HttpContext context)
    {
        var message = $"Good {this.options.GreetAt} {this.options.GreetTo}";
        await context.Response.WriteAsync(message);
    }
}

 

 

解决方案A:实例类型(Instance Type)


 

通过添加一个扩展方法类GreetingMiddlewareExtension,来配置中间件GreetingMiddleware,并传递参数GreetingOptions options

public static class GreetingMiddlewareExtension
{
    public static IApplicationBuilder UseGreeting(this IApplicationBuilder app, GreetingOptions options)
    {
        return app.UseMiddleware<GreetingMiddleware>(options);
    }
}

 

在ASP.NET Core项目中Startup类的Configure方法中,启用GreetingMiddleware中间件,并传递参数到中间件

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseGreeting(new GreetingOptions
    {
        GreetAt = "Morning",
        GreetTo = "Tahir"
    });
}

 

 

解决方案B:方法类型(Function Type)


 

通过添加一个扩展方法类GreetingMiddlewareExtension,来配置中间件GreetingMiddleware,并通过委托Action<GreetingOptions> configureOptions来传递参数GreetingOptions

public static class GreetingMiddlewareExtension
{
    public static IApplicationBuilder UseGreeting(this IApplicationBuilder app, Action<GreetingOptions> configureOptions)
    {
        var options = new GreetingOptions();
        configureOptions(options);

        return app.UseMiddleware<GreetingMiddleware>(options);
    }
}

 

在ASP.NET Core项目中Startup类的Configure方法中,启用GreetingMiddleware中间件,并通过委托Action<GreetingOptions>传递参数到中间件

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseGreeting(options =>
    {
        options.GreetAt = "Morning";
        options.GreetTo = "Tahir";
    });
}

 

 

讨论


 

在前面的一篇文章中我们讨论了,定义和使用中间件(Middleware)的最好方法是,将中间件定义在一个单独的类中,然后通过扩展方法将其添加到ASP.NET Core的中间件管道(pipeline)中。

 

我们可以通过上面介绍的解决方案A和B,将需要传递到中间件的参数都封装为一个POCO类,并创建一个扩展方法,用下面两种方式作为扩展方法的参数:

  • POCO实例(解决方案A)
  • 一个委托方法,随后通过调用该委托方法来创建并配置POCO实例(解决方案B)

注意:POCO实例是通过. UseMiddleware()方法的params object[]参数来传递到中间件的构造函数中的,也就是说我们可以通过params object[]来传递任意多个参数到中间件中,只要类型和中间件的构造函数参数匹配即可。我们还可以将依赖注入参数和POCO实例参数一起定义在中间件的构造函数中,如下所示:

public class GreetingMiddleware
{
    private readonly RequestDelegate next;
    private readonly GreetingOptions options;

    //IHostingEnvironment env是依赖注入参数,GreetingOptions options是POCO实例参数
    public GreetingMiddleware(RequestDelegate next, IHostingEnvironment env, GreetingOptions options)
    {
        string environmentName = env.EnvironmentName;

        this.next = next;
        this.options = options;
    }

    public async Task Invoke(
        HttpContext context)
    {
        var message = $"Good {this.options.GreetAt} {this.options.GreetTo}";
        await context.Response.WriteAsync(message);
    }
}

 

 

配置依赖注入服务


 

前面介绍的两种解决方案同样也可以用来配置依赖注入(dependency injection)服务的容器。

为了演示,我们先添加一个POCO类MessageOptions和用到的枚举MessageFormat

public enum MessageFormat
{
    None,
    Upper,
    Lower
}

public class MessageOptions
{
    public MessageFormat Format { get; set; }
}

 

然后添加一个依赖注入接口IMessageService,及其实现类MessageService

public interface IMessageService
{
    string FormatMessage(string message);
}

 

public class MessageService : IMessageService
{
    private readonly MessageOptions options;

    public MessageService(MessageOptions options)
    {
        this.options = options;
    }

    public string FormatMessage(string message)
    {
        // use options
        return this.options.Format == MessageFormat.None ? message :
                this.options.Format == MessageFormat.Upper ? message.ToUpper() :
                    message.ToLower();
    }
}

 

同样,接下来我们就用两种解决方案,来定义MessageService的扩展方法类MessageServiceExtension

 

 

解决方案A:实例类型(Instance Type)


 

public static class MessageServiceExtension
{
    // Instance Type
    public static IServiceCollection AddMessageFormatter(this IServiceCollection services, MessageOptions options)
    {
        return services.AddScoped<IMessageService>(factory =>
        {
            return new MessageService(options);
        });
    }
}

 

在ASP.NET Core项目中Startup类的ConfigureServices方法中,注册IMessageService和MessageService的依赖注入服务

// Instance Type
public void ConfigureServices(IServiceCollection services)
{
    services.AddMessageFormatter(new MessageOptions
    {
        Format = MessageFormat.Lower
    });
}

 

 

解决方案B:方法类型(Function Type)


 

public static class MessageServiceExtension
{
    // Function Type
    public static IServiceCollection AddMessageFormatter(this IServiceCollection services, Action<MessageOptions> configureOptions)
    {
        var options = new MessageOptions();
        configureOptions(options);

        return services.AddScoped<IMessageService>(factory =>
        {
            return new MessageService(options);
        });
    }
}

 

在ASP.NET Core项目中Startup类的ConfigureServices方法中,注册IMessageService和MessageService的依赖注入服务

// Function Type
public void ConfigureServices(IServiceCollection services)
{
    services.AddMessageFormatter(options =>
    {
        options.Format = MessageFormat.Lower;
    });
}

 

 

 

本文参考自:Passing Parameters to Middleware in ASP.NET Core 2.0

 

posted @ 2019-02-01 11:44  PowerCoder  阅读(1352)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3