我正在编写一个工具,需要对方法进行反射,如果方法的参数是复杂类型,则需要执行某些类型的操作,例如实例化等。
现在我看到了Type
变量中的IsPrimitive
属性。然而,它将string
和decimal
等类型显示为复杂类型,这在技术上并不是不正确的。然而,我真正想要的是能够区分开发人员创建的类类型和系统定义的数据类型。
有没有办法可以实现这个目标?
我正在编写一个工具,需要对方法进行反射,如果方法的参数是复杂类型,则需要执行某些类型的操作,例如实例化等。
现在我看到了Type
变量中的IsPrimitive
属性。然而,它将string
和decimal
等类型显示为复杂类型,这在技术上并不是不正确的。然而,我真正想要的是能够区分开发人员创建的类类型和系统定义的数据类型。
有没有办法可以实现这个目标?
decimal
确实是一个 "复杂类型";C# 也许有一个关键字来表示它,但它不是 CLI 原生的。对于字符串,你可以这么说 - 它实际上是一种独特的类型(大小不确定等等 - 唯一可以比较的是数组)。
然而,无法确定您在这里想要什么。最好的方法是检查已知的系统程序集(或者可能是签名密钥)。毕竟,我 可以编写一个名为 System.something.dll
或 Microsoft.something.dll
的程序集,并在 System.Foo.Bar
命名空间中定义类型(当然这还取决于你想要多么谨慎)。
通过属性或接口,让开发人员显式标记他们自己想要以特殊方式处理的类型可能更容易。
if (property.PropertyType.Namespace.StartsWith("MyApp.MyNamespace"))
{
// logic for properties in MyNamespace
}
我不确定是否有更优雅的方法,但我想如果您将类型的命名空间或程序集限定名称与 System 命名空间和/或系统程序集进行比较,那么它会很好地解决问题。
不太确定使用内置类型与用户创建的类型有何不同。更大的问题是创建没有无参构造函数的类型的实例。
无论你做什么,你都必须将它们转换为对象数组,以便你可以将它们传递给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
}