动态创建服务引用和使用服务

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态创建服务引用和使用服务相关的知识,希望对你有一定的参考价值。

我想做的是;我使用配置文件中的“WSDL”服务链接,并以编程方式使用服务,获取我将使用的方法的名称。

我静态使用并运行的代码片段如下,

ServiceName.serviceClientSoapClient= new ServiceName.serviceClientSoapClient();

string xmlStr = client.getValues();

而端点是,

<endpoint address="http://someservice.com/Service.asmx"
        binding="basicHttpBinding" bindingConfiguration="serviceClientSoap"
        contract="ServiceName.serviceClientSoap" name="serviceClientSoap" />

但是,我想以编程方式创建所有这些,例如;我的配置文件,

 <add key="serviceLink" value="http://someservice.com/Service.asmx"/>
 <add key="serviceClientClassName" value="serviceClientSoapClient"/>
 <add key="serviceMethod" value="getValues"/>

然后我想使用这个配置文件,并使用服务,获得结果。

我查看了以下链接,但这里是通过单一服务结构完成的。我希望它从配置文件中安装。

How to programmatically connect a client to a WCF service? How to: Use the ChannelFactory

答案

最好创建一个接口并将其实现为服务客户端。通过这种方式,您应该指定配置文件中所需的方法,参数和其他内容,并且难以管理。此外,您不能将结果对象用作已知类型类。

所以,你可以尝试这样的事情:

var url = ConfigurationManager.AppSettings["serviceLink"];
var serviceClientClassName = ConfigurationManager.AppSettings["serviceClientClassName"];
var serviceMethod = ConfigurationManager.AppSettings["serviceMethod"];
var endpoint = new EndpointAddress(new Uri(url));
//Specify the assembly of services library. I am assuming that the services are stored in the Executing Assembly
var serviceClient = Assembly.GetExecutingAssembly().GetTypes()
    .FirstOrDefault(x => x.Name == serviceClientClassName);//Find the service client type
var instance = Activator.CreateInstance(serviceClient); //Create a new instance of type
var methodInfo = serviceClient.GetMethod(serviceMethod); //Get method info
var result = methodInfo.Invoke(instance, new object[] {});  // Invoke it
另一答案

如果您只需要WCF CommunicationObject来处理RequestReply端点,则以下方法将为您执行此操作。

它接受有效的Request消息,endpoint和soapaction,并提供服务返回的原始xml。

如果你想给它任何其他的东西,那么你需要为Message实现一个替换为使用ServiceContract和OperationContract属性修饰的IRequestChannel

// give it a valid request message, endpoint and soapaction
static string CallService(string xml, string endpoint, string soapaction)
{
    string result = String.Empty;

    var binding = new BasicHttpBinding();

    // create a factory for a given binding and endpoint
    using (var client = new ChannelFactory<IRequestChannel>(binding, endpoint))
    {
        var anyChannel = client.CreateChannel(); // Implements IRequestChannel

        // create a soap message
        var req = Message.CreateMessage(
            MessageVersion.Soap11,
            soapaction,
            XDocument.Parse(xml).CreateReader());

        // invoke the service
        var response = anyChannel.Request(req);

        // assume we're OK
        if (!response.IsFault)
        {
            // get the body content of the reply
            var content = response.GetReaderAtBodyContents();
            // convert to string
            var xdoc = XDocument.Load(content.ReadSubtree());
            result = xdoc.ToString();
        }
        else
        {
            //throw or handle
            throw new Exception("panic");
        }
    }
    return result;
}

要使用上面的方法,您可以从配置文件中获取两个参数,或使用一些常量值:

var result = CallService(
   @"<GetData xmlns=""http://tempuri.org/""><value>42</value></GetData>",
   ConfigurationManager.AppSettings["serviceLink"],
   ConfigurationManager.AppSettings["serviceSoapAction"]);

// example without using appSettings
var result2 = CallService(
   @"<GetValues xmlns=""http://tempuri.org/""></GetValues>",
   "http://localhost:58642/service.svc",
   "http://tempuri.org/IService/GetValues");

请注意,除了以下内容之外,配置文件中不需要任何其他配置:

<appSettings>
    <add key="serviceLink" value="http://localhost:58642/service.svc"/>
    <add key="serviceSoapAction" value="http://tempuri.org/IService/GetData"/>
</appSettings>

使用服务的WSDL来找出soapaction:

 <wsdl:binding name="BasicHttpBinding_IService" type="tns:IService">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="GetData">
      <soap:operation soapAction="http://tempuri.org/IService/GetData" style="document"/>

并通过其portType和消息跟踪其路由,您将找到类型:

 <wsdl:types>
    <xs:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:import namespace="http://schemas.datacontract.org/2004/07/"/>
      <xs:element name="GetData">
        <xs:complexType>
          <xs:sequence>
            <xs:element minOccurs="0" name="value" type="xs:int"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>

您可以从中为GetData构造XML有效内容的形状:

<GetData xmlns="http://tempuri.org/">
    <value>42</value>
</GetData>

以上是关于动态创建服务引用和使用服务的主要内容,如果未能解决你的问题,请参考以下文章

你如何在片段中膨胀动态创建的对象?

记录:Web无引用无配置方式动态调用WCF服务

动态SQL基础概念复习(Javaweb作业5)

片段对话框对活动的松散引用

dubbo服务引用与集群容错

在android中动态创建选项卡并使用传入的参数加载片段