除未实例化的泛型类型外,通过链接Not Everything 派生自对象@Lippert 先生的博客由Gravell 先生的好答案指出,我建议找到满足您要求的其他类型可以自己完成。
现在,让我们从头开始解决这个问题。首先,您要弄清楚的类型应该在核心运行时库中,即mscorlib.dll
:
public static partial class MartinMulderExtensions {
public static IEnumerable<Type> GetMscorlibTypes() {
return
from assembly in AppDomain.CurrentDomain.GetAssemblies()
let name=assembly.ManifestModule.Name
where 0==String.Compare("mscorlib.dll", name, true)
from type in assembly.GetTypes()
select type;
}
}
然后,类型具有MakeXXXXType()
诸如MakeByRefType()
. 在这里,我们考虑了更多的可能性,即任何返回一个或多个类型的方法。由于我们对任意类型的参数的了解为零,因此我们认为方法采用零参数:
partial class MartinMulderExtensions {
public static IEnumerable<Type> GetRetrievableTypes(this Type type) {
var typesArray=(
from method in type.GetMethods()
where 0==method.GetParameters().Count()
let typeArray=
method.InvokeZeroArgumentMethodWhichReturnsTypeOrTypes(type)
where null!=typeArray
select typeArray).ToArray();
var types=
typesArray.Length>0
?typesArray.Aggregate(Enumerable.Union)
:Type.EmptyTypes;
return types.Union(new[] { type });
}
}
但是,对于 的实现InvokeZeroArgumentMethodWhichReturnsTypeOrTypes
,这种调用有几种无效的情况,例如GetGenericParameterConstraints()
在非泛型类型上调用;我们使用try-catch来避免这些情况:
partial class MartinMulderExtensions {
public static IEnumerable<Type>
InvokeZeroArgumentMethodWhichReturnsTypeOrTypes(
this MethodInfo method, Type t
) {
try {
if(typeof(Type)==method.ReturnType) {
var type=method.Invoke(t, null) as Type;
if(null!=type)
return new[] { type };
}
if(typeof(Type[])==method.ReturnType) {
var types=method.Invoke(t, null) as Type[];
if(types.Length>0)
return types;
}
}
catch(InvalidOperationException) {
}
catch(TargetInvocationException) {
}
catch(TargetException) {
}
return Type.EmptyTypes;
}
}
现在,要找出所需的类型。让我们逐步构建方法。第一步是定义所有可能类型的范围:
partial class MartinMulderExtensions {
public static Type[] GetDesiredTypes() {
return (
from type in MartinMulderExtensions.GetMscorlibTypes()
.Select(x => x.GetRetrievableTypes())
.Aggregate(Enumerable.Union)
然后,根据你所说的基本:
现在我的问题是:是否有更多这样的“异国情调”类型(除了 ByRef 类型和 type object
)是类(IsClass == true
)但没有基本类型(BaseType == null
)?
where null==type.BaseType
where type.IsClass
您还表示before answer
:
在你回答之前:我只指类型 where IsClass == true
!我的类型示例int
只是一个示例。它可以是任何类型。所以请不要:
where !type.IsInterface
where !type.IsValueType
where typeof(void)!=type
最后一步,让我们跳过已经回答的并完成方法:
where !type.IsByRef
where !type.IsPointer
select type
).ToArray();
}
}
所以现在,您可以调用MartinMulderExtensions.GetDesiredTypes()
以获取所需的类型:
public partial class TestClass {
public static void TestMethod() {
foreach(var type in MartinMulderExtensions.GetDesiredTypes())
Console.WriteLine(type);
}
}
对于完整的代码:
public static partial class MartinMulderExtensions {
public static IEnumerable<Type> GetMscorlibTypes() {
return
from assembly in AppDomain.CurrentDomain.GetAssemblies()
let name=assembly.ManifestModule.Name
where 0==String.Compare("mscorlib.dll", name, true)
from type in assembly.GetTypes()
select type;
}
public static IEnumerable<Type>
InvokeZeroArgumentMethodWhichReturnsTypeOrTypes(
this MethodInfo method, Type t
) {
try {
if(typeof(Type)==method.ReturnType) {
var type=method.Invoke(t, null) as Type;
if(null!=type)
return new[] { type };
}
if(typeof(Type[])==method.ReturnType) {
var types=method.Invoke(t, null) as Type[];
if(types.Length>0)
return types;
}
}
catch(InvalidOperationException) {
}
catch(TargetInvocationException) {
}
catch(TargetException) {
}
return Type.EmptyTypes;
}
public static IEnumerable<Type> GetRetrievableTypes(this Type type) {
var typesArray=(
from method in type.GetMethods()
where 0==method.GetParameters().Count()
let typeArray=
method.InvokeZeroArgumentMethodWhichReturnsTypeOrTypes(type)
where null!=typeArray
select typeArray).ToArray();
var types=
typesArray.Length>0
?typesArray.Aggregate(Enumerable.Union)
:Type.EmptyTypes;
return types.Union(new[] { type });
}
public static Type[] GetDesiredTypes() {
return (
from type in MartinMulderExtensions.GetMscorlibTypes()
.Select(x => x.GetRetrievableTypes())
.Aggregate(Enumerable.Union)
where null==type.BaseType
where type.IsClass
where !type.IsInterface
where !type.IsValueType
where typeof(void)!=type
where !type.IsByRef
where !type.IsPointer
select type
).ToArray();
}
}