vs-streamjsonrpc icon indicating copy to clipboard operation
vs-streamjsonrpc copied to clipboard

InvalidCastException while generating proxies

Open vasylmykytiukkryon opened this issue 3 years ago • 4 comments

Hey @AArnott, Thank you for your great efforts on this, really appreciate it!

I'm using vs-streamjsonrpc in my plugin framework scenario and looks like I found the bug. When I try to use Attach<T> method it throws the following exception: Unable to cast object of type '_proxy_PluginRpcContract.IGreeter_5143f248-4875-4810-b2d9-c9f6b0f4efeb' to type 'PluginRpcContract.IGreeter'.

   at StreamJsonRpc.JsonRpc.Attach[T](JsonRpcProxyOptions options) in D:\src\Samples\vs-streamjsonrpc\src\StreamJsonRpc\JsonRpc.cs:line 730
   at StreamJsonRpc.JsonRpc.Attach[T]() in D:\src\Samples\vs-streamjsonrpc\src\StreamJsonRpc\JsonRpc.cs:line 717
   at PluginB.Plugin.ExecuteAsync() in C:\Users\V.Mykytiuk\source\repos\StreamJsonRpcTest\PluginB\Plugin.cs:line 20
   at StreamJsonRpcTest.Program.<Main>d__0.MoveNext() in C:\Users\V.Mykytiuk\source\repos\StreamJsonRpcTest\StreamJsonRpcTest\Program.cs:line 32
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at StreamJsonRpcTest.Program.<Main>d__0.MoveNext() in C:\Users\V.Mykytiuk\source\repos\StreamJsonRpcTest\StreamJsonRpcTest\Program.cs:line 30
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at StreamJsonRpcTest.Program.<Main>d__0.MoveNext() in C:\Users\V.Mykytiuk\source\repos\StreamJsonRpcTest\StreamJsonRpcTest\Program.cs:line 30
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at StreamJsonRpcTest.Program.<Main>(String[] args)

It works fine for the first invocation, but all next invocations fail with that exception. I guess the problem is related to the multiple assemblies loaded in different Assembly Load Context. Each plugin (with its own dependencies) "lives" in a separate Assembly Load Context. The assembly where the contract (PluginRpcContract.IGreeter) for the proxy is defined also "lives" in the same ALC as the plugin itself, so there are multiple assemblies (PluginRpcContract) with the same name loaded in different ALCs.

I suppose the problem is related to ProxyGeneration.GetProxyModuleBuilder method, because when I commented out some code and return new ModuleBuilder for each interfaceType - it works and does not throw exception above.

Attaching the archive that reproduces the issue: StreamJsonRpcTest.zip

Could you please take a look? Maybe I am doing something wrong?

Thanks, Vasyl

vasylmykytiukkryon avatar Apr 21 '21 13:04 vasylmykytiukkryon

Hi @AArnott! Hope you are doing well these days.

Just kindly asking whether you had a chance to look into the issue? Is there any possibility that this fix will be on your roadmap any time soon?

Regards :)

vasylmykytiukkryon avatar May 27 '21 14:05 vasylmykytiukkryon

An interesting problem. I would certainly like JsonRpc proxies to work in the case of multiple ALCs. I don't think we have any tests to cover that scenario so I'm not too surprised if we have a bug in that area. I can't promise a timeline for fixing this at this point, but as I expect the fix won't take long, I'll optimistically schedule it for our 2.9 release.

AArnott avatar Jun 09 '21 20:06 AArnott

@vmykytiuk it's a runtime bug. https://github.com/dotnet/runtime/issues/53271 https://github.com/dotnet/runtime/issues/43685 https://github.com/dotnet/runtime/issues/30917

snikeguo avatar Jun 24 '21 15:06 snikeguo

@snikeguo, thanks for sharing. But it's not the same problem, since we don't use DispatchProxy in StreamJsonRpc.

AArnott avatar Jun 24 '21 16:06 AArnott