C# 只能在 Type.IsGenericParameter 为 true 的类型上调用方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1346238/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Method may only be called on a Type for which Type.IsGenericParameter is true
提问by sgmoore
I am getting this error on a routine which uses reflection to dump some object properties, something like the code below.
我在使用反射转储某些对象属性的例程中遇到此错误,类似于下面的代码。
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);
...
}
}
The actual error is "Exception has been thrown by the target of an invocation" with an inner exception of "Method may only be called on a Type for which Type.IsGenericParameter is true."
实际错误是“调用的目标已抛出异常”,内部异常为“只能在 Type.IsGenericParameter 为 true 的类型上调用方法”。
At this stage in the debugger obj appears as
在这个阶段,调试器中的 obj 显示为
{Name = "SqlConnection" FullName = "System.Data.SqlClient.SqlConnection"}
with the type System.RuntimeType
类型为 System.RuntimeType
The method m is {System.Reflection.MethodBase DeclaringMethod}
方法 m 是 {System.Reflection.MethodBase DeclaringMethod}
Note that obj is of type System.RuntimeType and members contains 188 items whereas a simple typeof(System.Data.SqlClient.SqlConnection).GetMembers(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance) only returns 65.
请注意,obj 是 System.RuntimeType 类型,其成员包含 188 个项目,而简单的 typeof(System.Data.SqlClient.SqlConnection).GetMembers(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance) 仅返回 65 个。
I tried checking isGenericParameter on both obj and p.PropertyType, but this seems to be false for most properties including those where p.GetValue works.
我尝试在 obj 和 p.PropertyType 上检查 isGenericParameter,但这对于大多数属性(包括 p.GetValue 起作用的属性)来说似乎是错误的。
So what exactly is a "Type for which Type.IsGenericParameter is true" and more importantly how do I avoid this error without a try/catch?
那么究竟什么是“Type.IsGenericParameter 为真的类型”,更重要的是如何在没有 try/catch 的情况下避免此错误?
采纳答案by Eric Smith
Firstly, you've made in incorrect assumption, that is, you've assumed that members
has returned the members of an instance of System.Data.SqlClient.SqlConnection
, which it has not. What has been returned are the members of an instance of System.Type
.
首先,您做出了错误的假设,也就是说,您假设members
已经返回了 的实例的成员System.Data.SqlClient.SqlConnection
,而实际上并没有。返回的是 的实例的成员System.Type
。
From the MSDN documentation for DeclaringType:
从DeclaringType的 MSDN 文档中:
Getting the
DeclaringMethod
property on a type whoseIsGenericParameter
property is false throws anInvalidOperationException
.
获取 属性为 false
DeclaringMethod
的类型的IsGenericParameter
属性会引发InvalidOperationException
.
So... it's understandable that an InvalidOperationException
is being thrown, since naturally, you're not dealing with an open generic type here. See Marc Gravells answerfor an explanation of open generic types.
所以……InvalidOperationException
抛出an是可以理解的,因为很自然地,您在这里处理的不是开放的泛型类型。有关开放泛型类型的解释,请参阅Marc Gravells 的回答。
回答by Marc Gravell
So what exactly is a "Type for which Type.IsGenericParameter is true"
那么究竟什么是“Type.IsGenericParameter 为真的类型”
That means it is a generic type argument in an open generic type - i.e. where we haven't picked a T
yet; for example:
这意味着它是开放泛型类型中的泛型类型参数——即我们还没有选择 a 的地方T
;例如:
// true
bool isGenParam = typeof(List<>).GetGenericArguments()[0].IsGenericParameter;
// false (T is System.Int32)
bool isGenParam = typeof(List<int>).GetGenericArguments()[0].IsGenericParameter;
So; have you got some open generics hanging around? Perhaps if you can give an example of where you got your obj
from?
所以; 你有一些开放的泛型吗?也许你能举个例子说明你从哪里来的obj
?
回答by AnthonyWJones
All the clues are in there. The type of the obj is the Type
class itself (or rather the strange RuntimeType derivative).
所有的线索都在里面。obj 的类型是Type
类本身(或者更确切地说是奇怪的 RuntimeType 派生类)。
At the point of failure you loop has arrived the Type
class property called DeclaringMethod
. However the type that this instance of the Type
class is describing is System.Data.SqlClient.SqlConnection
which is not a Generic Type of a method.
在您循环的失败点到达了Type
名为DeclaringMethod
. 然而,这个Type
类的实例所描述的System.Data.SqlClient.SqlConnection
类型不是方法的通用类型。
Hence attempting to invoke the get on DeclaringMethod results in the exception.
因此,尝试在 DeclaringMethod 上调用 get 会导致异常。
The key is you are examining the type of the class Type
. Its a bit circular but think of this:-
关键是您正在检查类的类型Type
。它有点圆,但想想这个:-
SqlConnection s = new SqlConnection();
Type t = s.GetType()
Type ouch = t.GetType()
What is class ouch describing?
class ouch 描述的是什么?
回答by stevemegson
How do I avoid this error without a try/catch?
如何在没有 try/catch 的情况下避免此错误?
You almost certainly can't. When you call p.GetValue
, you're calling the getter on that property, which could throw any kind of exception. For example, SqlConnection.ServerVersion will throw an exception if the connection is closed, and you have to handle that.
你几乎肯定不能。当您调用 时p.GetValue
,您正在调用该属性上的 getter,这可能会引发任何类型的异常。例如,如果连接关闭,SqlConnection.ServerVersion 将抛出异常,您必须处理它。
Where are these extra members coming from?
这些额外的成员来自哪里?
Your obj
already contains the RuntimeType
object representing SqlConnection
, rather than an instance of SqlConnection
. obj.GetMembers()
would return the 65 members of the SqlConnection
class, but by calling GetType()
again, you get the 188 members of RuntimeType
.
您obj
已经包含RuntimeType
表示的对象SqlConnection
,而不是 的实例SqlConnection
。obj.GetMembers()
将返回SqlConnection
该类的 65 个成员,但通过GetType()
再次调用,您将获得RuntimeType
.
What is IsGenericParameter
?
什么是IsGenericParameter
?
Instead of representing a class, you can have an instance of RuntimeType
that represents a generic parameter to a class or method (The T
and TOutput
in List<T>.ConvertAll<TOutput>
. In this case, DeclaringMethod
on the object representing TOutput
would let you get a MethodInfo
object representing the ConvertAll<>
method. However, when the RuntimeType
represents a class, the idea of a declaring method makes no sense. That's why reading the property causes the exception that you saw.
您可以拥有一个RuntimeType
代表类或方法的泛型参数的实例,而不是代表一个类(TheT
和TOutput
in List<T>.ConvertAll<TOutput>
。在这种情况下,DeclaringMethod
在代表的对象TOutput
上将让您获得MethodInfo
代表该ConvertAll<>
方法的对象。但是,当RuntimeType
代表一个类,声明方法的想法是没有意义的。这就是为什么读取属性会导致您看到的异常。
回答by aseman arabsorkhi
My problem was solved by deleting repetitive fields and tables in my model and commented defining query and deleted store: in Model.edmx XML File.
我的问题是通过删除模型中的重复字段和表来解决的,并在 Model.edmx XML 文件中注释了定义查询和删除的存储。