请考虑以下代码:
IEnumerable<Type> oneParameterTypes = Assembly.GetAssembly(typeof(object))
.GetTypes()
.Where(t => t.IsGenericType)
.Where(t => t.GetGenericArguments().Length == 1)
.Where(t => t.GetGenericArguments().Single().GetGenericParameterConstraints().Length == 0);
oneParameterTypes
应该包含System.dll
程序集中的所有泛型类型,这些类型可以传递一个泛型类型参数,并且不对其应用任何约束。
现在,让我们传入一个类型参数:
IEnumerable<Type> intParameterTypes = oneParameterTypes.Select(t => t.MakeGenericType(typeof(int)))
.ToList();
这应该有用,对吗?我的意思是,oneParameterTypes
中的所有类型都没有类型约束,因此System.Int32
应该是有效的类型。
然而,该行引发了以下异常:
GenericArguments [0],&#39; System.Int32&#39;,on&#39; System.RuntimeType + ListBuilder`1 [T]&#39;违反了&#39; T&#39;。
的约束
这个ListBuilder'1
类型是什么?为什么它在oneParameterTypes
中有类型约束?为什么我的Where
过滤器无效?
答案 0 :(得分:2)
我认为克里斯是正确的。
试试这样:
IEnumerable<Type> oneParameterTypes = Assembly.GetAssembly(typeof (object))
.GetTypes()
.Where(t => t.IsGenericType)
.Where(t => t.GetGenericArguments().Length == 1)
.Where(t => t.GetGenericArguments().Single().GetGenericParameterConstraints().Length == 0 &&
!genericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint);
});
答案 1 :(得分:1)
文档并不清楚Type.GetGenericParameterConstraints
实际查找的内容:
使用IsClass属性确定约束是否是基类约束;如果属性返回false,则约束是接口约束。 如果类型参数没有类约束且没有接口约束,则返回空数组。
您可以隐含地理解它只会检查基类或接口约束。要全面了解存在约束的情况,您需要对GenericParameterAttributes
进行额外检查。您可以使用HasFlag
或按位掩码:
IEnumerable<Type> oneParameterTypes = Assembly.GetAssembly(typeof(object))
.GetTypes()
.Where(t => t.IsGenericType)
.Where(t => t.GetGenericArguments().Length == 1)
.Where(t => t.GetGenericArguments().Single().GetGenericParameterConstraints().Length == 0 && !t.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint);
答案 2 :(得分:0)
typeof()或.GetType()方法不返回实际的类,而是返回Type Object表示,这将帮助我们将类型名称用作字符串。
相反,您可以使用反射类并查找该类型的类并将其用作参数