Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 动态创建服务引用并使用服务_C#_Web Services_Wcf - Fatal编程技术网

C# 动态创建服务引用并使用服务

C# 动态创建服务引用并使用服务,c#,web-services,wcf,C#,Web Services,Wcf,我想做的是;我使用配置文件中的“WSDL”服务链接,并以编程方式使用该服务,使用我将使用的方法的名称 我静态使用并运行的代码片段如下所示 ServiceName.serviceClientSoapClient= new ServiceName.serviceClientSoapClient(); string xmlStr = client.getValues(); 终点是 <endpoint address="http://someservice.com/Service.asmx"

我想做的是;我使用配置文件中的“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"/>

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

因此,您可以尝试类似的方法:

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端点,那么下面的方法就可以为您做到这一点

它接受有效的请求消息、端点和soapaction,并提供服务返回的原始xml

如果您想给它任何其他的东西,那么您需要实现一个替代方案,用于修饰ServiceContract和OperationContract属性

// 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;
}
//为其提供有效的请求消息、端点和soapaction
静态字符串调用服务(字符串xml、字符串端点、字符串soapaction)
{
字符串结果=string.Empty;
var binding=新的BasicHttpBinding();
//为给定绑定和端点创建工厂
使用(var client=newchannelfactory(绑定,端点))
{
var anyChannel=client.CreateChannel();//实现IRequestChannel
//创建soap消息
var req=Message.CreateMessage(
MessageVersion.Soap11,
肥皂剧,
Parse(xml.CreateReader());
//调用服务
var响应=任何通道请求(req);
//假设我们没事
如果(!response.IsFault)
{
//获取回复的正文内容
var content=response.GetReaderAtBodyContents();
//转换为字符串
var xdoc=XDocument.Load(content.ReadSubtree());
结果=xdoc.ToString();
}
其他的
{
//投掷或处理
抛出新异常(“恐慌”);
}
}
返回结果;
}
要使用上述方法,您可以从配置文件中获取两个参数,或使用一些常量值:

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");
var result=CallService(
@"42",
ConfigurationManager.AppSettings[“serviceLink”],
ConfigurationManager.AppSettings[“serviceSoapAction”];
//不使用appSettings的示例
var result2=CallService(
@"",
"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和message的路径,您可以找到以下类型:

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

42

您是否为这些端点中的每一个都有一个接口(您是否可以配置这些端点,或者有方法识别它们)?或者您总是希望响应的主体作为字符串返回吗?它返回xml文件。当xml文件到达时,我动态地设置下一个进程。在那一点上我没有问题。不幸的是,这些端点没有接口。我认为真正的问题在这里@现在,我添加并运行该服务作为引用。但是如果我能在运行时添加服务,一切都将是动态的。但就目前而言,你的解决方案是可行的@雷曼