• 如何传递参数给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

  • 相关阅读:
    android系统webview使用input实现选择文件并预览
    在列表中动态设置元素的id
    Vue使用Clipboard.JS在h5页面中复制内容
    Vue使用v-for显示列表时,数组里的item数据更新,视图中列表不同步更新的解决方法
    Vue子组件和根组件的关系
    Vue生命周期和钩子函数及使用keeplive缓存页面不重新加载
    Python与数据结构[3] -> 树/Tree[0] -> 二叉树及遍历二叉树的 Python 实现
    Python与数据结构[2] -> 队列/Queue[0] -> 数组队列的 Python 实现
    Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算
    Python与数据结构[1] -> 栈/Stack[0] -> 链表栈与数组栈的 Python 实现
  • 原文地址:https://www.cnblogs.com/OpenCoder/p/10345312.html
Copyright © 2020-2023  润新知