将泛型类型参数应用于返回泛型参数的方法时出现 MissingMethodException
我有一个名为 DynamicInvoke 的方法,如下所示:
public static object InvokeDynamic(Delegate d, object[] args)
{
Type[] tparams = d.Method.DeclaringType.GetGenericArguments()
.Concat(d.Method.GetGenericArguments())
.ToArray();
Type dt = d.GetType().DeclaringType;
if (dt.ContainsGenericParameters)
dt = dt.MakeGenericType(tparams);
IDirectInvoke di = dt.GetConstructor(Type.EmptyTypes).Invoke(null) as IDirectInvoke;
object o = di.Invoke(d.Method, d.Target, args);
return o;
}
它在以下上下文中使用(是的,这是使用 Mono.Cecil 以编程方式生成的代码,并使用 ILSpy 反转):
[Processed, Distributed]
[Serializable]
public class GenericsTest<A, B> : ITransparent, ISerializable where A : new() where B : ITest
{
private class Method3__InvokeDirect3<C> : IDirectInvoke
{
[CompilerGenerated]
public delegate C Method3__DistributedDelegate4();
public object Invoke(MethodInfo method, object instance, object[] parameters)
{
GenericsTest<A, B>.Method3__InvokeDirect3<C>.Method3__DistributedDelegate4 method3__DistributedDelegate = (GenericsTest<A, B>.Method3__InvokeDirect3<C>.Method3__DistributedDelegate4)Delegate.CreateDelegate(typeof(GenericsTest<A, B>.Method3__InvokeDirect3<C>.Method3__DistributedDelegate4), instance, method);
return method3__DistributedDelegate.Invoke();
}
}
public C Method3<C>()
{
MulticastDelegate d = new GenericsTest<A, B>.Method3__InvokeDirect3<C>.Method3__DistributedDelegate4(this.Method3__Distributed0<C>);
object[] args = new object[0];
return (C)DpmEntrypoint.Invoke(d, args);
}
[CompilerGenerated]
private C Method3__Distributed0<C>()
{
return default(C);
}
}
现在,如果 a) GenericsTest 没有泛型参数,则代码可以正确运行或 b)该方法没有通用参数(并且我有其他类和方法来验证这一点)。只有当类和方法都包含泛型参数时才会出现问题。
调用 di.Invoke 时,出现以下异常:
System.MissingMethodException was unhandled
Message="Method not found: '**UNKNOWN TYPE** Method3__DistributedDelegate4.Invoke()'."
Source="Examples.ServerClient"
StackTrace:
at Examples.ServerClient.GenericsTest`2.Method3__InvokeDirect3`1.Invoke(MethodInfo method, Object instance, Object[] parameters)
at Process4.Providers.DpmEntrypoint.InvokeDynamic(Delegate d, Object[] args) in C:\Server Storage\Projects\Redpoint\Dx\Process4\Providers\Dpm.cs:line 249
at Process4.Providers.DpmEntrypoint.Invoke(Delegate d, Object[] args) in C:\Server Storage\Projects\Redpoint\Dx\Process4\Providers\Dpm.cs:line 359
at Examples.ServerClient.GenericsTest`2.Method3[C]()
at Examples.ServerClient.Program.GenericsTest() in C:\Server Storage\Projects\Redpoint\Dx\Examples.ServerClient\Program.cs:line 76
at Examples.ServerClient.Program.Main(String[] args) in C:\Server Storage\Projects\Redpoint\Dx\Examples.ServerClient\Program.cs:line 18
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
鉴于我已经检查了 ILSpy 中的结果,并且 IL 和元数据在功能上等同于 C# 编译器本身生成的结果(通过将代码复制到 .cs 文件中进行测试)并编译它),我现在认为是 Invoke 方法的运行时使用导致了这个问题。
奇怪的效果之一是构造函数被成功调用,并且 Visual Studio 在检查新创建的 IDirectInvoke 对象时正确报告类型(它仅在调用 Invoke 时抛出异常),但如前所述,Invoke 的 IL 与C# 生成。
有谁知道这种情况下可能出现什么问题?
编辑:还有一件事,这只发生在直接返回分配给方法的泛型参数的方法上(因此,如果该方法返回 A、B 或包含以下参数的另一个泛型类型实例,则不会发生这种情况) A、B 或 C;在这种情况下会发生,因为该方法直接返回 C 类型的对象。
I have a method called DynamicInvoke that is as follows:
public static object InvokeDynamic(Delegate d, object[] args)
{
Type[] tparams = d.Method.DeclaringType.GetGenericArguments()
.Concat(d.Method.GetGenericArguments())
.ToArray();
Type dt = d.GetType().DeclaringType;
if (dt.ContainsGenericParameters)
dt = dt.MakeGenericType(tparams);
IDirectInvoke di = dt.GetConstructor(Type.EmptyTypes).Invoke(null) as IDirectInvoke;
object o = di.Invoke(d.Method, d.Target, args);
return o;
}
It is used in the following context (and yes this is programmatically generated code using Mono.Cecil and reversed using ILSpy):
[Processed, Distributed]
[Serializable]
public class GenericsTest<A, B> : ITransparent, ISerializable where A : new() where B : ITest
{
private class Method3__InvokeDirect3<C> : IDirectInvoke
{
[CompilerGenerated]
public delegate C Method3__DistributedDelegate4();
public object Invoke(MethodInfo method, object instance, object[] parameters)
{
GenericsTest<A, B>.Method3__InvokeDirect3<C>.Method3__DistributedDelegate4 method3__DistributedDelegate = (GenericsTest<A, B>.Method3__InvokeDirect3<C>.Method3__DistributedDelegate4)Delegate.CreateDelegate(typeof(GenericsTest<A, B>.Method3__InvokeDirect3<C>.Method3__DistributedDelegate4), instance, method);
return method3__DistributedDelegate.Invoke();
}
}
public C Method3<C>()
{
MulticastDelegate d = new GenericsTest<A, B>.Method3__InvokeDirect3<C>.Method3__DistributedDelegate4(this.Method3__Distributed0<C>);
object[] args = new object[0];
return (C)DpmEntrypoint.Invoke(d, args);
}
[CompilerGenerated]
private C Method3__Distributed0<C>()
{
return default(C);
}
}
Now the code operates correctly if either a) GenericsTest has no generic parameters or b) the method has no generic parameters (and I have other classes and methods that verify this). Only when both the class and the methods contain generic parameters does the problem occur.
When di.Invoke is called, I get the following exception:
System.MissingMethodException was unhandled
Message="Method not found: '**UNKNOWN TYPE** Method3__DistributedDelegate4.Invoke()'."
Source="Examples.ServerClient"
StackTrace:
at Examples.ServerClient.GenericsTest`2.Method3__InvokeDirect3`1.Invoke(MethodInfo method, Object instance, Object[] parameters)
at Process4.Providers.DpmEntrypoint.InvokeDynamic(Delegate d, Object[] args) in C:\Server Storage\Projects\Redpoint\Dx\Process4\Providers\Dpm.cs:line 249
at Process4.Providers.DpmEntrypoint.Invoke(Delegate d, Object[] args) in C:\Server Storage\Projects\Redpoint\Dx\Process4\Providers\Dpm.cs:line 359
at Examples.ServerClient.GenericsTest`2.Method3[C]()
at Examples.ServerClient.Program.GenericsTest() in C:\Server Storage\Projects\Redpoint\Dx\Examples.ServerClient\Program.cs:line 76
at Examples.ServerClient.Program.Main(String[] args) in C:\Server Storage\Projects\Redpoint\Dx\Examples.ServerClient\Program.cs:line 18
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
Given that I've checked the results in ILSpy and the IL and metadata is functionally equivalent to that generated by the C# compiler itself (tested by copying the code into a .cs file and compiling it), I'm now thinking that it's the runtime use of the Invoke method that's causing this issue.
One of the odd effects is that the constructor is called successfully AND Visual Studio reports the types correctly when inspecting the newly created IDirectInvoke object (it only throws the exception when calling Invoke) and yet as noted previously, the IL for Invoke is identical to what C# generates.
Does anyone know what the issue could be in this case?
EDIT: One more thing, this only occurs on methods that directly return a generic parameter assigned to a method (so it does not occur if the method returns A, B or another generic type instance that contains parameters of A, B or C; in this case it occurs because the method directly returns an object of type C).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论