如何用ArchUnitNet的.BeAssignableTo()检查泛型类型?
解决ArchUnitNet中泛型类型的可分配性检查问题
直接使用.BeAssignableTo("MediatR.IBaseRequest")无法生效的核心原因是:这个方法匹配的是非泛型的接口类型,而你要检查的类实现的是带参数的泛型版本(如IBaseRequest<T>、IBaseRequest<T1,T2>等),两者类型不匹配。
以下是两种实用的解决方案:
方案1:针对特定参数数量的泛型接口检查
如果明确要检查的泛型接口参数数量(比如1个、2个),可以直接通过泛型类型定义来匹配:
// 获取1个参数的IBaseRequest泛型定义 var baseRequestGenericType1 = typeof(MediatR.IBaseRequest<>).GetGenericTypeDefinition(); // 获取2个参数的IBaseRequest泛型定义 var baseRequestGenericType2 = typeof(MediatR.IBaseRequest<,>).GetGenericTypeDefinition(); // 编写检查规则 ArchRuleDefinition.Classes() .That().ArePublic() // 根据需求调整过滤条件 .Should().ImplementInterfaceWhere(iface => iface.IsGenericType && (iface.GetGenericTypeDefinition() == baseRequestGenericType1 || iface.GetGenericTypeDefinition() == baseRequestGenericType2) ) .Check(yourTargetAssembly);
方案2:匹配任意参数数量的IBaseRequest泛型接口
如果需要支持1到N个任意参数数量的泛型版本,可以通过检查泛型类型的全名前缀实现(.NET中泛型类型全名会以\+参数数量结尾,比如IBaseRequest<T>的全名是MediatR.IBaseRequest1`):
ArchRuleDefinition.Classes() .That().ArePublic() .Should().Satisfy(classType => classType.GetInterfaces() .Any(iface => iface.IsGenericType && iface.GetGenericTypeDefinition().FullName.StartsWith("MediatR.IBaseRequest`") ) ) .Check(yourTargetAssembly);
补充简化写法
如果你的ArchUnitNet版本支持ImplementGenericInterface扩展方法,可进一步简化:
ArchRuleDefinition.Classes() .That().ImplementGenericInterface(typeof(MediatR.IBaseRequest<>)) .Or().ImplementGenericInterface(typeof(MediatR.IBaseRequest<,>)) // 按需添加更多参数数量的泛型接口 .Should().BeSealed() // 替换为你的具体断言需求 .Check(yourTargetAssembly);
内容的提问来源于stack exchange,提问作者Ashok Kumar Korupolu
相关产品推荐
相关产品推荐

