Reputation: 2020
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
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