如何确定对象类型是不是为内置系统类型
Posted
技术标签:
【中文标题】如何确定对象类型是不是为内置系统类型【英文标题】:How to determine if a object type is a built in system type如何确定对象类型是否为内置系统类型 【发布时间】:2011-08-21 09:56:06 【问题描述】:我正在编写一个简单的List<t>
到 CSV 转换器。我的转换器检查 List 中的所有 t
并抓取所有公共属性并将它们放入 CSV。
当您将使用具有一些属性的简单类时,我的代码效果很好(如预期的那样)。
我想让List<t>
到 CSV 转换器也接受系统类型,例如字符串和整数。对于这些系统类型,我不想获得它们的公共属性(例如长度、字符等)。因此我想检查对象是否是系统类型。系统类型是指内置的 .Net 类型之一,例如 string, int32, double
等。
使用 GetType() 我可以找到以下内容:
string myName = "Joe Doe";
bool isPrimitive = myName.GetType().IsPrimitive; // False
bool isSealed = myName.GetType().IsSealed; // True
// From memory all of the System types are sealed.
bool isValueType = myName.GetType().IsValueType; // False
// LinqPad users: isPrimitive.Dump();isSealed.Dump();isValueType.Dump();
如何确定变量 myName 是否为内置系统类型? (假设我们不知道它是一个字符串)
【问题讨论】:
你认为什么是系统类型,什么不是? 我不知道正确的术语,但我认为string
、int32
是一种系统类型,而Employee
显然不是。基本上任何不是由编译器创建的类型。
您是否只查找编译器内置的类型?还是 System
命名空间中的所有类型?
@Gabe 哦,我知道你要去哪里,只需将根命名空间与“系统”进行比较?
【参考方案1】:
以下是几种可能性中的几种:
myName.GetType().Namespace == "System"
myName.GetType().Namespace.StartsWith("System")
myName.GetType().Module.ScopeName == "CommonLanguageRuntimeLibrary"
【讨论】:
这些太棒了! Module ScopeName 是一个可靠的方法。谢谢! 这应该是公认的答案。ScopeName
防火
@JeremyChild System.Security.Cryptography.Pkcs.SignedCms
类型的Module.ScopeName
等于System.Security.dll
,因此不应只检查一个"CommonLanguageRuntimeLibrary"
。我添加了moduleScope == "CommonLanguageRuntimeLibrary" || moduleScope.StartsWith("System") || sourceType.Namespace.StartsWith("System") || sourceType.Namespace.StartsWith("Microsoft")
之类的支票【参考方案2】:
myName.GetType().Namespace
如果它是内置类型,这将返回 System。
【讨论】:
你不需要在字符串上调用ToString
。
编辑了答案以删除多余的调用。
这回答了问题,但没有解决问题。你怎么知道System
命名空间中的所有值类型都是可以忽略其属性的?你真的要对System.ArgIterator
或System.Nullable<Employee>
这样做吗?
基于命名空间的方法可能会导致冲突。详情见以下评论:***.com/a/44682414/6627992
@NetMage ,程序员可以在不同的程序集中使用自定义类型扩展系统命名空间。如果我们将使用字符串命名空间,我们可能会得到不正确的结果,因为这种类型不是 内置语言 (new System.CustomType().GetType().Namespace) == "System"【参考方案3】:
如果您无法准确定义“内置系统类型”是什么,那么您似乎可能不知道给出的任何答案中的类型。更有可能您想要做的只是列出您不想使用的类型。有一个“IsSimpleType”方法,只检查各种类型。
您可能正在寻找的另一件事是原始类型。如果是这样看:
Type.IsPrimitive (http://msdn.microsoft.com/en-us/library/system.type.isprimitive.aspx)
基本类型有布尔、字节、SByte、Int16、UInt16、Int32、 UInt32、Int64、UInt64、IntPtr、UIntPtr、Char、Double 和 Single。
这不包括字符串,但您可以手动添加...
另见How To Test if Type is Primitive
【讨论】:
【参考方案4】:基于命名空间的方法可能会导致冲突。
还有另一种可靠且简单的方法:
static bool IsSystemType(this Type type) => type.Assembly == typeof(object).Assembly;
或者更优化一点,缓存系统程序集:
static readonly Assembly SystemAssembly = typeof(object).Assembly;
static bool IsSystemType(this Type type) => type.Assembly == SystemAssembly;
【讨论】:
用System.Windows.Point
试试这个。
'System.Windows.Point' 不是语言 build in 系统类型,如 object、int、string、DateTime、TimeSpan 等。似乎这个问题是关于 build in类型。
我不同意所谓的内置:为什么Action<,,,,,,,>
(8 个参数)与Action<,,,,,,,,>
(9 个参数)不同?或者为什么System.Collections.Hashtable
或System.Collections.ArrayList
应该是内置的,而System.Collections.BitArray
不是?或者System.IO.FileAttributes
不是System.IO.FileOptions
是内置的?
@NetMage 如果我们考虑经典的 .NET Framework 4.7.2,所有这些类型都包含在 mscorelib 程序集中,但 System.Core 中的 Action (9 args) 除外。因此,您可以根据自己的愿景自定义内置程序集列表。我只想说,Assemblies 的比较比字符串命名空间的比较更安全。【参考方案5】:
我认为这是最好的可能性:
private static bool IsBulitinType(Type type)
return (type == typeof(object) || Type.GetTypeCode(type) != TypeCode.Object);
【讨论】:
只是一个警告:如果对象实现 IConvertible 并返回其他内容,Type.GetTypeCode() 可以返回非对象代码:msdn.microsoft.com/en-us/library/system.typecode.aspx 如果一个对象属性是一个字符串,它会在这里返回true。如果目的是确定该类型是否为自定义类型,那么这将不起作用。System.TimeSpan
丢失【参考方案6】:
我正在反思地构建一些东西,发现IsSecurityCritical
属性似乎为此目的工作;然而,这只是因为 my 程序集的信任级别不够高,无法翻转那个位。
有点笑;谢天谢地,我找到了这个问题,并将相应地进行调整。
注意:IsSecurityCritical
属性仅在 .NetFramework > 4 时存在
我可能会选择;以下来自上一个答案。
myName.GetType().Module.ScopeName == "CommonLanguageRuntimeLibrary"
但是,经过一些调整;例如使其成为Type
上的扩展方法并为CommonLanguageRuntimeLibrary
const
【讨论】:
您是否与 CoreCLR 核对以确保 ScopeName 保持不变?【参考方案7】:鉴于围绕现有答案的注意事项,我将建议一个仅限 Windows 的解决方案:
public static class TypeExt
public static bool IsBuiltin(this Type aType) => new[] "/dotnet/shared/microsoft", "/windows/microsoft.net" .Any(p => aType.Assembly.CodeBase.ToLowerInvariant().Contains(p));
大概在其他支持的操作系统上也有类似的路径。
【讨论】:
【参考方案8】:我更喜欢
colType.FullName.StartsWith("System")
然后
colType.Namespace.StartsWith("System")
因为Namespace
可能为空。
【讨论】:
以上是关于如何确定对象类型是不是为内置系统类型的主要内容,如果未能解决你的问题,请参考以下文章