如何确定.NET类型是自定义结构体?

9
如何编写一个简单的方法来检查一个具体类型是否是自定义结构(使用public struct { };创建)。
仅检查Type.IsValueType是不够的,因为它也适用于intlong等类型,而添加!IsPrimitiveType的检查将不包括decimalDateTime和可能的其他值类型。我知道大多数内置值类型实际上是“结构体”,但我只想检查“自定义结构体”。
这些问题大多相同,但没有我需要的答案: 编辑:从提到的答案中,“检查‘System’前缀”是最稳定的(尽管仍然是一个hack)。我最终决定创建一个属性,你必须用它装饰结构体,以便框架将其作为自定义结构体选择。(我认为另一种选择是创建一个空接口,让结构体实现该空接口,但属性方式似乎更优雅)
下面是我原始的自定义结构体检查器,如果有人感兴趣:
type.IsValueType && !type.IsPrimitive && !type.Namespace.StartsWith("System") && !type.IsEnum

1
只是出于好奇,你为什么想要检测这个? - Joren
Fluent NHibernate + Auto Mapping:将所有自定义结构设置为组件(值对象)进行处理;将任何其他值类型设置为组件(如DateTime或decimal)将导致整个框架崩溃(至少在mono下是这样)。 - SztupY
5个回答

8

在框架中定义的结构体和自己定义的结构体没有区别。

一些想法可能包括:

  • 保留框架结构体的白名单,排除这些结构体;
  • 确定类型所定义的程序集(DLL),并保留框架程序集的白名单。
  • 确定类型所在的命名空间,并排除框架的命名空间。

在使用Fluent NHibernate的评论背景下,白名单中列出“众所周知”的结构体将是最佳选择。该列表短小精悍,易于理解,并且可能永远不会改变。 - Paul Turner
同意,当你发现每一个导致崩溃的问题时,将其添加到白名单(或黑名单或任何你称之为的列表)中,并继续。该框架没有太多的结构体。 - stusmith
是的,但不幸的是,这方面没有列表。如果您遗漏了某些内容,并在稍后使用该结构,则不会知道为什么框架开始崩溃。 - SztupY

5

好的,DateTime、decimal等类型符合你的要求。就CLR而言,它们是自定义结构体。这是一种hack方法,但你可以检查命名空间是否以“System”开头。


当然,你自己的命名空间可以以System开头... :) 没有人会这样做,对吧? - Nelson Rothermel
2
是的,这就是为什么我称之为 hack 的原因。 - Matt Greer
@MattGreer:顺便说一句,这个技巧很棒,我想不到 :) 谢谢 - Mubashar

3
将上述注释放入扩展方法中:
public static class ReflectionExtensions {
        public static bool IsCustomValueType(this Type type) {            
               return type.IsValueType && !type.IsPrimitive && type.Namespace != null && !type.Namespace.StartsWith("System.");
        }
    }

应该可以正常工作


2

您可以检查结构类型是否属于System命名空间中的任何位置。但是这并不是一个可靠的解决方案。


-1

你是否有与该类型匹配的值?调用ToString方法并检查返回的字符串是否以“{”开头。

如果您没有值,请检查它是否具有无参数构造函数。如果没有,那么它是一个构造函数。如果有,则使用Activator创建一个实例,并再次调用ToString方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接