我在使用反射转储一些对象属性的例程上遇到此错误,类似于下面的代码。
MemberInfo[] members = obj.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance) ;
foreach (MemberInfo m in members)
{
PropertyInfo p = m as PropertyInfo;
if (p != null)
{
object po = p.GetValue(obj, null);
...
}
}
实际错误是“调用目标已抛出异常” 内部异常“只能在Type.IsGenericParameter为true的Type上调用Method。”
在调试器的这个阶段,obj显示为
{Name = "SqlConnection" FullName = "System.Data.SqlClient.SqlConnection"}
,类型为System.RuntimeType
方法m是{System.Reflection.MethodBase DeclaringMethod}
请注意,obj的类型为System.RuntimeType,成员包含188个项目,而简单 typeof(System.Data.SqlClient.SqlConnection).GetMembers(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)仅返回65.
我尝试在obj和p.PropertyType上检查isGenericParameter,但对于大多数属性,包括那些p.GetValue工作的属性,这似乎都是错误的。
那究竟什么是“Type.IsGenericParameter为真的类型”,更重要的是 如果没有try / catch,我该如何避免这个错误?
答案 0 :(得分:14)
那究竟什么是“Type.IsGenericParameter为真的类型”
这意味着它是开放泛型类型中的泛型类型参数 - 即我们尚未选择T
的地方;例如:
// true
bool isGenParam = typeof(List<>).GetGenericArguments()[0].IsGenericParameter;
// false (T is System.Int32)
bool isGenParam = typeof(List<int>).GetGenericArguments()[0].IsGenericParameter;
因此;你有一些开放的仿制药吗?也许你可以举例说明你从obj
获得的地方?
答案 1 :(得分:13)
首先,你做出了错误的假设,也就是说,你假设members
已经返回System.Data.SqlClient.SqlConnection
实例的成员,而它没有。返回的是System.Type
实例的成员。
来自DeclaringType的MSDN文档:
获取
DeclaringMethod
属性 在IsGenericParameter
的类型上 属性是假的InvalidOperationException
。
所以......抛出InvalidOperationException
是可以理解的,因为很自然,你不会在这里处理一个开放的泛型类型。有关开放泛型类型的说明,请参阅Marc Gravells answer。
答案 2 :(得分:3)
所有的线索都在那里。 obj的类型是Type
类本身(或者更确切地说是奇怪的RuntimeType派生类)。
在失败时,你的循环已经到达名为DeclaringMethod
的Type
类属性。但是,Type
类的这个实例所描述的类型是System.Data.SqlClient.SqlConnection
,它不是方法的泛型类型。
因此,尝试调用get on DeclaringMethod导致异常。
关键是你正在研究班级Type
的类型。它有点循环但想到这个: -
SqlConnection s = new SqlConnection();
Type t = s.GetType()
Type ouch = t.GetType()
什么是类ouch描述?
答案 3 :(得分:1)
如果没有try / catch,我该如何避免此错误?
你几乎肯定不能。当你调用p.GetValue
时,你正在调用该属性的getter,这可能会抛出任何异常。例如,如果连接关闭,SqlConnection.ServerVersion将抛出异常,您必须处理它。
这些额外成员来自哪里?
您的obj
已包含代表RuntimeType
的{{1}}对象,而不是SqlConnection
的实例。 SqlConnection
将返回obj.GetMembers()
班级的65名成员,但再次致电SqlConnection
,您将获得GetType()
的188名成员。
什么是RuntimeType
?
您可以拥有IsGenericParameter
的实例,而不是代表一个类,该实例代表类或方法的通用参数(RuntimeType
中的T
和TOutput
。在这种情况下,代表List<T>.ConvertAll<TOutput>
的对象上的DeclaringMethod
将允许您获得表示TOutput
方法的MethodInfo
对象。但是,当ConvertAll<>
表示类时,声明方法的想法毫无意义。这就是为什么读取属性会导致你看到的异常。
答案 4 :(得分:1)
我的问题已解决,方法是删除模型中的重复字段和表,并注释定义查询并删除存储:Model.edmx XML文件中。