natemcmaster / DotNetCorePlugins

.NET Core library for dynamically loading code

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Question] Help with a InvalidCastException when calling wcf services

jpareias opened this issue · comments

I have two plugins that both call wcf services. Both are referring System.ServiceModel with version 4.7. I'm marking both plugins as unloadable.

Only one of the plugins can call his service (always the first to be executed). Whenever the other plugin calls a service, the InvalidCastException is thrown (Exception: Unable to cast object of type 'generatedProxy_2' to type 'System.ServiceModel.Channels.ServiceChannelProxy').

The only way to get around the problem is to have each plugin reference a different version of System.Model. I also tried to make System.ServiceModel has PrivateAssemblies.

it is necessary to do something different to better isolate each plugin?

It's hard to say. Can you share steps to reproduce this error? It's hard to tell what is happening from your description.

Sorry, sometimes it all makes sense just in my head.

I have an application that at a given point in the user registration process sends the user data to other systems/application. Each user data synchronization is done by a separate plugin.
My application provides an interface with a method that each plugin must implement.
After the user registers, the application loads all the plugin's that implement this interface and executes the method for each one.
After successful loaded the plugin, the plugin is not unloaded. They are kept in memory.

If more than one of the plugins makes a calls to soap services using these libraries (System.ServiceModel and his dependencies). Only the first plugin to run does it successfully. Any of the following gives the error 'generatedProxy_2' to type 'System.ServiceModel.Channels.ServiceChannelProxy'.

If I have each plugin using a different version of the libraries. The error no longer occurs.

Small code sample:

var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
var factory = new ChannelFactory<UserServices>(basicHttpBinding, new EndpointAddress("https://services/user.svc"));
var serviceClient = factory.CreateChannel();

The error occurs in the last line of code.

Thanks for more detail. I'm still not sure how to go about finding a solution here. Based on what you said, I have a starting point, but no definite answers.

Hint 1: you said the error says something about a generated proxy. Is WCF using System.Reflection.Emit to generate new types? Or using Microsoft.CodeAnalysis to do runtime complications?

Hint 2: error doesn't occur if using different WCF versions. Maybe WCF had a bug? Try upgrading?

My first thought was precisely that. I validate with other web services, but I always got the same error.
I believe WCF is using System.Reflection.Emit. The plugin's are generating their code through visual studio 2019. Visual studio is using Microsoft.Tools.ServiceModel.Svcutil v2.0.2.

I ended up definitely solving the problem by passing the creation of the wcf client to the host. The plug-ins will use a class made available by the host through DI to create the wcf client. The code that i show above will be executed in this class.

Ok. Closing because I think your solution to move WCF into the host is a good move. .NET assembly load context and system.ref.emit apparently don't play nice. There's only so much this library can do to coerce certain plugin behaviors out of .NET's runtime.

@natemcmaster I was running into the same issue and found a solution thanks to this post.
Maybe add this to the FAQ, as it seems to be a general thing with WCF services.