使用反射确定基本类型的复杂类型

10

我正在编写一个工具,需要对方法进行反射,如果方法的参数是复杂类型,则需要执行某些类型的操作,例如实例化等。

现在我看到了Type变量中的IsPrimitive属性。然而,它将stringdecimal等类型显示为复杂类型,这在技术上并不是不正确的。然而,我真正想要的是能够区分开发人员创建的类类型和系统定义的数据类型。

有没有办法可以实现这个目标?

4个回答

8

decimal 确实是一个 "复杂类型";C# 也许有一个关键字来表示它,但它不是 CLI 原生的。对于字符串,你可以这么说 - 它实际上是一种独特的类型(大小不确定等等 - 唯一可以比较的是数组)。

然而,无法确定您在这里想要什么。最好的方法是检查已知的系统程序集(或者可能是签名密钥)。毕竟, 可以编写一个名为 System.something.dllMicrosoft.something.dll 的程序集,并在 System.Foo.Bar 命名空间中定义类型(当然这还取决于你想要多么谨慎)。

通过属性或接口,让开发人员显式标记他们自己想要以特殊方式处理的类型可能更容易。


在C#中,字符串是明显的复杂类型。它们被定义为类而不是结构体,这就是区别所在,但字符串的行为也不是概念上的原始类型。它们在C#中的使用类似于原始类型,但这主要是通过一些巧妙的运算符重载和一些特殊的语言特性(如C#处理字符串字面量)来实现的。 - Stephen M. Redd
@Stephen - 我不同意; 结构体与类不是这里的重点。我可以像类型一样编写自定义结构体,等等。而且,“string”中的“特殊”远不止于像运算符这样的语言特性。 - Marc Gravell
我认为这可能只是语义问题,取决于你对“复杂”的定义,而C#并没有正式使用“复杂类型”这个术语。它有像“自定义”和“值类型”这样的术语,而字符串都不是。我认为它们在概念上是复杂的,因为字符串的数据存储为一组不是字符串的项的数组...因此,在字符串中使用数据取决于比从内存中简单获取基础值类型更复杂的行为。但是你对复杂的定义可能不同。 - Stephen M. Redd

5
在搜索时,我遇到了这个帖子。我正在寻找一个解决方案,后来发现你也可以检查命名空间,看看属性是否在你自己的命名空间中定义。
if (property.PropertyType.Namespace.StartsWith("MyApp.MyNamespace"))
{ 
      // logic for properties in MyNamespace
}

希望这篇文章能帮助到某些人。

2

我不确定是否有更优雅的方法,但我想如果您将类型的命名空间或程序集限定名称与 System 命名空间和/或系统程序集进行比较,那么它会很好地解决问题。


0

不太确定使用内置类型与用户创建的类型有何不同。更大的问题是创建没有无参构造函数的类型的实例。

无论你做什么,你都必须将它们转换为对象数组,以便你可以将它们传递给MethodInfo.Invoke,所以在某个时候你需要做Activator.CreateInstance

如果您提供一个UI,让用户在字段中输入内容,然后按下按钮调用方法,您最好的策略是使用反射来查找类型上的TryParse/Parse静态方法,并调用这些方法以验证/解析输入。

这里是一个代码片段,对于大多数可以从字符串转换的系统类型都可以隐式地工作:

var parseMethod = typeof(int).GetMethods().FirstOrDefault(
    m => m.IsStatic && 
        m.Name == "TryParse" && 
        m.GetParameters().Length == 2 && 
        m.GetParameters()[0].ParameterType == typeof(string) && 
        m.GetParameters()[1].IsOut);
if(parseMethod != null) {
    bool result = (bool)parseMethod.Invoke(null, new object[]{"45", null});
    //result == true
    result = (bool)parseMethod.Invoke(null, new object[] { "blah", null });
    //result = false
}

实际上,创建没有无参构造函数(甚至是私有的)的类型的实例并不是什么大问题,但是你需要非常小心;不建议在大多数代码中使用 - 只适用于诸如序列化 API 等特定场景。 - Marc Gravell

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