user304582
user304582

Reputation: 2020

C# cast generic type

I have an interesting problem which takes me beyond my C# comfort zone. By dynamically inspecting a Web service WSDL using the WsdlImporter and CodeDomProvider classes, I can generate and compile to an assembly the client proxy code to the Web service. This includes the service client class which is declared as follows:

public partial class SomeServiceClient : System.ServiceModel.ClientBase<ISomeService>, ISomeService {...}

Note that the name of the client class and the name of the ISomeService contract are dynamic - I don't know them in advance. I can instantiate an object of this class dynamically using:

string serviceClientName = "SomeServiceClient";// I derive this through some processing of the WSDL
object client = webServiceAssembly.CreateInstance(serviceClientName , false, System.Reflection.BindingFlags.CreateInstance, null, new object[] { serviceEndpoint.Binding, serviceEndpoint.Address }, System.Globalization.CultureInfo.CurrentCulture, null);

However, if I need to set ClientCredentials in this client class, then I cannot work out how to do this. I thought that I would be able to just cast the client object to the System.ServiceModel.ClientBase generic class, and then reference the ClientCredentials property. However, the following compiles but fails at runtime:

System.Net.NetworkCredential networkCredential = new System.Net.NetworkCredential(username, password, domain);
((System.ServiceModel.ClientBase<IServiceChannel>)client).ClientCredentials.Windows.ClientCredential = networkCredential;

Is there some way to specify the cast dynamically, or is there some way to set the credentials without this cast? Thanks for any help! Martin

Upvotes: 1

Views: 1758

Answers (1)

Moha Dehghan
Moha Dehghan

Reputation: 18472

If you have shared the exception, we could get you a better help, but this is what I guess:

Your class hierarchies are like this:

public interface ISomeService : System.ServiceModel.IServiceChannel
{
    ...
}

public class SomeServiceClient : System.ServiceModel.ClientBase<ISomeService>
{
}

and you are trying to cast SomeServiceClient to System.ServiceModel.ClientBase<IServiceChannel>. Sadly you cannot do that, C# 4 has a feature called Covariance that allows upcasting of generic type arguments, but that only work with interfaces, not concrete classes.

So the other options is using reflection:

ClientCredentials cc = (ClientCredentials)client.GetType().GetProperty("ClientCredentials").GetValue(client,null);
cc.Windows.ClientCredential = networkCredential;

That should work without problem (I've not tested it, so if it didn't work, tell me the problem so I can fix it).

Upvotes: 2

Related Questions