如何检查字符串中的类型是否为真实类型
本文关键字:类型 是否 真实 字符串 何检查 检查 | 更新日期: 2023-09-27 18:01:14
如果我有一个类型的字符串表示,例如"List<string>"
或"int"
。。。
有没有办法检查这是否是一个真正的.net类型?
例如,如果我有"List<Crap>"
,那么我想返回false,因为Crap
不是.net中的真实类型。如果我有"string"
或"Dictionary<string, object>"
,那么我想要返回true。
这可能吗?
谢谢。
如果您确定您的对象不可为null,则可以使用
item.GetType().Namespace.StartsWith("System")
如果没有,你可以创建一个系统对象列表,然后检查你的对象是否在列表中
List<Type> sysTypes = Assembly.GetExecutingAssembly()
.GetType().Module.Assembly.GetExportedTypes().ToList();
if (sysTypes.Contains(item.GetType())) {
// do something usefull
}
使用Type.GetType
例如:
string typeString = "System.String";
if(Type.GetType(typeString) != null)
{
//It's a real type
}
编辑:有一点需要注意,如果类型不在当前程序集中,则必须使用程序集限定名称对其进行完全限定。
第二版:借用Amson的答案:
var types = Assembly.GetExecutingAssembly().GetType().Module.Assembly.GetExportedTypes()
bool isReal = types.Any(x=>x.FullName == typeString);
然而,这仍然需要一些字符串操作来处理泛型。由于List<String>.FullName
是:
System.Collections.Generic.List`1[[System.String,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089]]`
第三版:在字符串操作方面,我从Dictionary<string,List<string>>
开始提出了这个问题:
Type type2 = typeof(Dictionary<string, List<string>>);
string typeString = type2.FullName;
int endOfType = typeString.IndexOf('`');
string mainType = typeString.Substring(0,endOfType);
mainType = mainType.Split('.').Last(); // this equals "Dictionary"
var genString = typeString.Substring(endOfType + 3);
string[] generics = genString.Split('[', ']');
generics = generics.Where(s => s != "" && s!= ",").ToArray();
它还没有出现在泛型上(尽管它也不太(,但我们现在至少可以比较基本类型了!(尽管我们也需要在这里检查是否有没有通用参数(。
如果我能找到解决方案,我会在今晚晚些时候回家时更新。
第4.5版:成功
以下代码将把Type.FullName中的值转换为可读的值:
/// <summary>
/// Converts a type's full name into a human readable string
/// </summary>
/// <param name="type">The type to convert</param>
/// <returns>Type formatted as follows: Dictionary<List<String>,Queue<Int32>>
/// Or for an open generic (e.g. Action<,>) returns Action<,></returns>
private static string ConvertTypeToReadableString(Type type)
{
string typeString = type.FullName;
int endOfType = 0;
if (typeString.Contains('`'))
{
//We have generic arguments
endOfType = typeString.IndexOf('`');
string mainType = typeString.Substring(0, endOfType);
mainType = mainType.Split('.').Last(); // this equals "Dictionary"
//Use this for namespace qualified names instead:
//return typeString
string result = mainType + "<";
var genString = typeString.Substring(endOfType + 3);
//Get number of generic arguments to expect.
int argCount = 0;
int tempArgCount = 0;
int i = 1;
while (i <= genString.Length && Int32.TryParse(genString.Substring(0, i), out tempArgCount))
{
i++;
argCount = tempArgCount;
}
string[] generics = genString.Split('[', ']');
generics = generics.Where(s => s != "" && s != "," && !s.StartsWith(",")).ToArray();
if (generics.Length < argCount)
{
//Assume an open generic
for(int x= 0; x< argCount-1; x++)
{
result += ",";
}
result += ">";
}
else
{
result += ParseGenerics(generics, argCount) + ">";
}
return result;
}
else
{
//No generic arguments
return typeString.Split('.').Last();
//Use this for namespace qualified names instead:
//return typeString;
}
}
/// <summary>
/// Convert generic arguments into simplified strings
/// </summary>
/// <param name="generics">List of strings, each containing one generic argument.</param>
/// <returns>Single string of format Item1,Item2,Item3<Item4,Item5></returns>
public static string ParseGenerics(string[] generics, int genericArgs)
{
string result = "";
int index = 0;
while(genericArgs > 0)
{
string generic = generics[index];
if (generic.Contains('`'))
{
//Another generic
int genericIndex = generic.IndexOf('`');
string mainType = generic.Substring(0, genericIndex).Split('.').Last();
//Use this if you want namespace-qualified names:
//string mainType = generic.Substring(0,genericIndex);
int i = 1;
//Get number of generic arguments to expect.
int argCount = 0;
int tempArgCount = 0;
while (genericIndex + 1 + i <= generic.Length && Int32.TryParse(generic.Substring(genericIndex + 1, i), out tempArgCount))
{
i++;
argCount = tempArgCount;
}
//Parse internal generics
result += mainType + "<" + ParseGenerics(generics.Skip(index + 1).ToArray(),argCount) + ">";
index += argCount;
}
else
{
//Get type name
result += generic.Split(',').First().Split('.').Last();
//Use this if you want namespace-qualified names:
//result += generic.Split(',').First();
}
result += ",";
genericArgs--;
index++;
}
//remove trailing comma
return result.Substring(0, result.Length - 1);
}
示例用法:
bool isRealType = false;
string typeString = "Dictionary<string,List<string>>".Replace(" ", string.empty).ToLowerInvariant();
var types = Assembly.GetExecutingAssembly().GetType().Module.Assembly.GetExportedTypes();
isRealType = types.Any(t=> ConvertTypeToReadableString(t).ToLowerInvariant().Equals(typeString));
如果您希望将命名空间限定的名称放入(例如System.String而不仅仅是String(,请取消注释相关注释。
在这之后,你可能唯一想做的就是使用查找表将积分类型转换为它们的类名(例如int到Int32(,但我把它留给你练习。
第五版:只剩下一个问题。我的答案现在可以很好地进行转换,即使是使用开放泛型类型,但您仍然需要考虑Assembly.GetExecutingAssembly().GetType().Module.Assembly.GetExportedTypes();
将只返回开放泛型这一事实,并检查您的字符串中是否有正确数量的args。从我现在的情况来看,这是非常可行的,但我必须睡觉。