1

我有一个有趣的问题,它让我超出了我的 C# 舒适区。通过使用 WsdlImporter 和 CodeDomProvider 类动态检查 Web 服务 WSDL,我可以生成 Web 服务的客户端代理代码并将其编译为程序集。这包括声明如下的服务客户端类:

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

请注意,客户端类的名称和 ISomeService 契约的名称是动态的——我事先并不知道它们。我可以使用以下方法动态实例化此类的对象:

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);

但是,如果我需要在此客户端类中设置 ClientCredentials,那么我无法弄清楚如何执行此操作。我认为我可以将客户端对象强制转换为 System.ServiceModel.ClientBase 泛型类,然后引用 ClientCredentials 属性。但是,以下编译但在运行时失败:

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

是否有某种方法可以动态指定演员表,或者是否有某种方法可以在没有此演员表的情况下设置凭据?谢谢你的帮助!马丁

4

1 回答 1

2

如果您分享了异常,我们可以为您提供更好的帮助,但这是我的猜测:

你的类层次结构是这样的:

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

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

并且您正在尝试转换SomeServiceClientSystem.ServiceModel.ClientBase<IServiceChannel>. 遗憾的是你不能这样做,C# 4 有一个称为协变的特性,它允许向上转换泛型类型参数,但它只适用于接口,而不适用于具体类。

所以其他选项是使用反射:

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

这应该没有问题(我没有测试过,所以如果它不起作用,请告诉我问题,以便我解决它)。

于 2012-07-24T05:12:38.110 回答