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

  • 相关阅读:
    《RabbitMQ 实战》读书笔记
    使用jstack命令查看CPU高占用的问题记录
    两种常见的单元测试方式(笔记)
    Apache Solr入门教程(转)
    搜索引擎选择: Elasticsearch与Solr(转)
    CopyOnWriteArrayList与Collections.synchronizedList的性能对比(转)
    理解list和vector的区别
    从上往下打印出二叉树的每个节点,同层节点从左至右打印。
    TypeError: Object function (req, res, next) { app.handle(req, res, next); } has no method 'configure'
    Cannot find module 'crc'
  • 原文地址:https://www.cnblogs.com/OpenCoder/p/10345312.html
Copyright © 2020-2023  润新知