在.NET Core(MS.DI)中使用类型约束注册通用类型

编程入门 行业动态 更新时间:2024-10-26 19:27:26
本文介绍了在.NET Core(MS.DI)中使用类型约束注册通用类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个通用接口 IPipelineBehavior< TRequest,TResponse> (来自MediatR).我正在尝试为此接口注册特定的行为,如下所示:

services.AddTransient(typeof(IPipelineBehavior<,>)),typeof(ValidationMiddleware<,>)));

ValidationMiddleware 实现了 IPipelineBehavior ,如下所示:

公共类ValidationMiddleware< TRequest,TResponse>:IPipelineBehavior< TRequest,结果< TResponse>>.

Result 是一个自定义类,我希望所有MediatR IRequestHandlers返回.

应用运行时,服务容器给我以下错误:

System.ArgumentException:实现类型'StudentManagement.App.Middleware.ValidationMiddleware 2 [StudentManagement.App.Students.DisenrollStudentCommand,StudentManagement.App.Result 1 [System.Object]]'无法转换为服务类型'MediatR.IPipelineBehavior 2 [StudentManagement.App.Students.DisenrollStudentCommand,StudentManagement.App.Result 1 [System.Object]]'

我不明白为什么,因为它们显然在运行时都具有相同的类型参数.我的猜测是 Result< TResponse> 位由于某种原因引起了错误,因为其他行为仅在实现 IPipelineBehavior< TRequest,TResponse> 时才能正常工作.>

有人知道我为什么收到此错误,以及解决该问题需要做什么吗?

解决方案

MS.DI不支持您希望实现的目标.在处理通用类型时,.NET Core的内置DI容器非常有限(甚至天真).

例如,以下是三种通用类型的(基本的)用例,而MS.DI不支持所有这些用例:

//示例通用抽象公共接口IGeneric< TKey,TValue>其中TKey:struct {}//类型与抽象类型不同的泛型类型公共类MonoGeneric< TKey>:IGeneric< TKey,字符串>其中TKey:struct {}//以不同的顺序输入泛型类型公共类SwappedGeneric< TValue,TKey>:IGeneric< TKey,TValue>其中TKey:struct {}//泛型类型不完全映射到抽象类型的类型//注意:这是您的用例.公共类ConstrainedGeneric< TKey,TValue>:IGeneric< TKey,List< TValue>>其中TKey:struct {}//登记services.AddTransient(typeof(IGeneric ,,),typeof(MonoGeneric,)));services.AddTransient(typeof(IGeneric ,,),typeof(SwappedGeneric ,,)));services.AddTransient(typeof(IGeneric ,,),typeof(ConstrainedGeneric ,,)));//用法//应该对任何注册都有效,但对所有注册都无效!provider.GetRequiredService< IGeneric< int,字符串>>();

不仅不支持此操作,而且MS.DI引发的异常消息将非常无助且令人困惑.

IMO,您的用例非常有效,这就是为什么许多DI容器实际上都支持该用例的原因.我的建议:选择一个更成熟的DI容器,并测试它是否支持您要应用泛型的方式.

I have a generic interface IPipelineBehavior<TRequest, TResponse> (from MediatR). I'm trying to register a specific behavior for this interface as follows:

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationMiddleware<,>));

ValidationMiddleware implements IPipelineBehavior like so:

public class ValidationMiddleware<TRequest, TResponse> : IPipelineBehavior<TRequest, Result<TResponse>>

Result is a custom class I want all of my MediatR IRequestHandlers to return.

When the app runs, the service container gives me the following error:

System.ArgumentException: Implementation type 'StudentManagement.App.Middleware.ValidationMiddleware2[StudentManagement.App.Students.DisenrollStudentCommand,StudentManagement.App.Result1[System.Object]]' can't be converted to service type 'MediatR.IPipelineBehavior2[StudentManagement.App.Students.DisenrollStudentCommand,StudentManagement.App.Result1[System.Object]]'

I can't see why because they clearly both have the same type arguments at runtime. My guess is that the Result<TResponse> bit is causing the error for some reason, because other behaviors work fine when they just implement IPipelineBehavior<TRequest, TResponse>.

Does anyone understand why I'm getting this error, and what I need to do to solve it?

解决方案

What you wish to achieve is not supported in MS.DI. .NET Core's built-in DI Container is very limited (or perhaps even naive) when it comes to handling generic types.

For instance, here are three (rather basic) use cases for generic types, all not supported by MS.DI:

// Example generic abstraction public interface IGeneric<TKey, TValue> where TKey : struct { } // Type with a different number of generic types than the abstraction public class MonoGeneric<TKey> : IGeneric<TKey, string> where TKey : struct { } // Type with the generic types in a different order public class SwappedGeneric<TValue, TKey> : IGeneric<TKey, TValue> where TKey : struct { } // Type where the generic types don't exactly map to those of the abstraction // NOTE: This is your use case. public class ConstrainedGeneric<TKey, TValue> : IGeneric<TKey, List<TValue>> where TKey : struct { } // Registration services.AddTransient(typeof(IGeneric<,>), typeof(MonoGeneric<>)); services.AddTransient(typeof(IGeneric<,>), typeof(SwappedGeneric<,>)); services.AddTransient(typeof(IGeneric<,>), typeof(ConstrainedGeneric<,>)); // Usage // Should work on any of the registrations, but it fails on all! provider.GetRequiredService<IGeneric<int, string>>();

Not only is this not supported, the exception messages thrown by MS.DI will be very unhelpful and confusing.

IMO, your use case is very valid, which is why many DI Containers actually support this use case. My advise: pick a more mature DI Container and test whether it supports the way you want to apply generics.

更多推荐

在.NET Core(MS.DI)中使用类型约束注册通用类型

本文发布于:2023-11-17 11:39:20,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1609891.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:类型   Core   NET   DI   MS

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!