using MessagePack;
using MessagePack.Resolvers;
using Microsoft.Extensions.Options;
namespace Dpz.Core.WebApi.MessagePackFormatters;
/// <summary>
/// 格式化选项设置
/// </summary>
public class MessagePackFormatterMvcOptionsSetup(
IOptions<MessagePackFormatterOptions> messagePackFormatterOptions
) : IConfigureOptions<MvcOptions>
{
private readonly IOptions<MessagePackFormatterOptions> _messagePackFormatterOptions =
messagePackFormatterOptions
?? throw new ArgumentNullException(nameof(messagePackFormatterOptions));
/// <inheritdoc />
/// <exception cref="T:System.InvalidOperationException">不支持的类型</exception>
/// <exception cref="T:System.ArgumentNullException"><paramref name="options" /> is <see langword="null" /></exception>
public void Configure(MvcOptions options)
{
ArgumentNullException.ThrowIfNull(options);
var formatterOptions = _messagePackFormatterOptions.Value;
var supportedMediaTypes = formatterOptions
.MediaTypes.Where(t => !string.IsNullOrWhiteSpace(t))
.ToArray();
if (supportedMediaTypes.Length == 0)
{
throw new InvalidOperationException("No supported media types were specified.");
}
var msgpackOptions = MessagePackSerializerOptions.Standard;
msgpackOptions = msgpackOptions.WithResolver(
formatterOptions.FormatterResolver ?? ContractlessStandardResolver.Instance
);
msgpackOptions = msgpackOptions
.WithAllowAssemblyVersionMismatch(formatterOptions.AllowAssemblyVersionMismatch)
.WithCompression(formatterOptions.Compression)
.WithOldSpec(formatterOptions.UseOldSpecification)
.WithOmitAssemblyVersion(formatterOptions.OmitAssemblyVersion);
options.InputFormatters.Add(
new MessagePackInputFormatter(msgpackOptions, supportedMediaTypes)
);
options.OutputFormatters.Add(
new MessagePackOutputFormatter(msgpackOptions, supportedMediaTypes)
);
foreach (var fileExtension in formatterOptions.FileExtensions)
{
options.FormatterMappings.SetMediaTypeMappingForFormat(
fileExtension,
supportedMediaTypes[0]
);
}
}
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
这段代码实现了一个用于在 ASP.NET Core MVC 中注册 MessagePack 编/解码格式化器(input/output formatter)的 IConfigureOptions
总体职责
- 通过依赖注入接收 IOptions
,读取用户配置(支持的媒体类型、resolver、压缩、兼容性等)。 - 构建 MessagePackSerializerOptions(MessagePack-CSharp 的选项),并基于这些选项创建并注册输入/输出格式化器到 MvcOptions 中。
- 为指定的文件扩展名设置格式到媒体类型的映射(FormatterMappings),以便通过扩展名或 format 参数识别 MessagePack。
主要流程(按代码块)
- 构造器和字段检查
- 构造函数注入 IOptions
并在为 null 时抛出 ArgumentNullException。
- Configure 方法入口参数检查
- 对传入的 MvcOptions 做 ArgumentNullException.ThrowIfNull 检查。
- 获取并验证支持的媒体类型
- 从 messagePackFormatterOptions.Value.MediaTypes 过滤空白字符串,得到 supportedMediaTypes。
- 如果 supportedMediaTypes 为空,抛出 InvalidOperationException("No supported media types were specified."),说明配置中必须至少指定一个媒体类型(例如 "application/x-msgpack")。
- 构建 MessagePackSerializerOptions
- 以 MessagePackSerializerOptions.Standard 为起点。
- 使用 formatterOptions.FormatterResolver(若为 null 则默认 ContractlessStandardResolver.Instance)设置解析器。
- 依次调用 WithAllowAssemblyVersionMismatch、WithCompression、WithOldSpec、WithOmitAssemblyVersion 来从配置应用对应的行为(这些选项影响序列化时的程序集版本兼容、是否启用压缩、是否使用旧版规范、是否省略程序集版本号等)。
- 注册输入/输出格式化器
- 将新的 MessagePackInputFormatter 和 MessagePackOutputFormatter(使用构建好的 msgpackOptions 和 supportedMediaTypes)分别添加到 options.InputFormatters 和 options.OutputFormatters。这样 MVC 能够处理 Content-Type 为指定媒体类型的请求体并以该格式返回响应。
- 文件扩展名到媒体类型的映射
- 遍历 formatterOptions.FileExtensions,将每个扩展名映射到 supportedMediaTypes[0](首选媒体类型),通过 options.FormatterMappings.SetMediaTypeMappingForFormat。这样例如访问 /api/xxx.format(或基于扩展名的路由策略)时可以推断使用 MessagePack。
异常与边界
- 构造时若注入的 IOptions 为 null 抛 ArgumentNullException。
- Configure 时若 options 为 null 抛 ArgumentNullException。
- 若未配置任何有效媒体类型抛 InvalidOperationException。
使用情境(简述)
- 在 Startup/Program 中注册 MessagePackFormatterOptions 并把该 IConfigureOptions 实例加入 DI(或通过扩展方法调用将其注册),从而在整个应用中启用 MessagePack 作为请求/响应格式之一。常见的 media type 如 "application/x-msgpack" 或 "application/msgpack"。
补充说明
- ContractlessStandardResolver 是 MessagePack-CSharp 提供的一种解析器,常用于无需显式 [MessagePackObject]/键名映射的“合同无关”序列化。
- MessagePackInputFormatter/MessagePackOutputFormatter 在代码中是格式化器实现(此处未显示),它们负责把 HTTP 请求体反序列化为控制器参数,或把返回值序列化为 MessagePack 二进制响应。
如果你想,我可以再帮你:
- 展示 MessagePackFormatterOptions 的可能定义与默认值示例;
- 示范如何在 Program.cs/Startup.cs 中注册此配置类并启用 MessagePack。
AI 正在分析代码…
评论加载中...