检查对象是否满足通用参数约束

Sim*_*mon 13 c# generics reflection

我有一个类似于下面的界面:

public interface IInterface<T>
    where T : IInterface<T>
{
}
Run Code Online (Sandbox Code Playgroud)

现在我需要使用反射创建一个表示此接口的类型,例如

typeof(IInterface<>).MakeGenericType(someType);
Run Code Online (Sandbox Code Playgroud)

但是,我实际上并不知道什么类型的'someType'将在运行时之前,并且该类型可能无法作为通用接口的类型参数有效,因此MakeGenericType失败.

问题是,如何检查'someType'是否对泛型约束有效?

Jon*_*eet 19

说实话,最简单的方法是只调用MakeGenericType并捕获ArgumentException如果任何类型参数错误(或者你的类型参数数量错误)将抛出的方法.

虽然你可以使用Type.GetGenericParameterConstraints查找制约然后制定出他们每个人的手段,这将是丑陋的和容易出错的代码.

通常不喜欢建议"只是尝试并抓住",但在这种情况下,我认为这将是最可靠的方法.否则你只是重新实现CLR将要执行的检查 - 你有什么机会完美地重新实现它们?:)

  • @Joel:是的,这是懒人的方法,*通常*使用异常是错误的检查方式.但是,在这种情况下,我们试图检查一些可能变得非常复杂的东西,并且该检查已经编码到其他地方.如果框架有一个TryMakeGenericType,那就太棒了...... (6认同)
  • @Joel:关于规则的重要之处在于知道它们为什么*通常*适用,以及什么时候可以打破它们:) (2认同)

jas*_*son 6

这个有可能。给定约束,您使用Type.GenericParameterAttributes和掩码

GenericParameterAttributes.ReferenceTypeConstraint
GenericParameterAttributes.NotNullableValueTypeConstraint
GenericParameterAttributes.DefaultConstructorConstraint
Run Code Online (Sandbox Code Playgroud)

class检查、struct或约束是否存在new()。您可以轻松检查给定类型是否满足这些约束(第一个很容易实现(使用Type.IsClass),第二个有点棘手,但您可以使用反射来完成,第三个有一个单元测试将检测到的小问题(Type.GetConstructor(new Type[0])不不返回值类型的默认构造函数,但您知道它们无论如何都有默认构造函数)。

之后,您可以Type.GetGenericParameterConstraints获取类型层次结构约束(where T : Base, IInterface类似约束)并运行它们以检查给定类型是否满足它们。