2017-12-18 352 views
2

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

+0

你每個端點都有一個接口(你可以配置這些接口或者有一種方法來識別它們)?或者你總是期望響應的主體被返回爲一個字符串? – rene

+0

它正在返回xml文件。當xml文件到達時,我動態地設置下一個進程。我在這一點上沒有問題。不幸的是,這些端點沒有接口。無論如何,我認爲真正的問題在這裏。 @rene –

回答

2

它可以更好地創建一個接口,並實現它的服務客戶。通過這種方式,您應該指定配置文件中所需的方法,參數和其他內容,並且難以管理。另外,您不能將結果對象用作已知的類型類。

所以,你可以嘗試這樣的事情:

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

現在,我添加並運行該服務作爲參考。但是如果我可以在運行時添加服務,那麼一切都將是動態的。但現在,您的解決方案正在發揮作用。 @雨人 –

0

如果你需要的是WCF CommunicationObject的處理RequestReply端點,下面的方法會爲你做的。

它需要一個有效的請求消息,端點和一個soapaction,並給出服務返回的原始xml。

如果您想給它其他任何東西然後Message您需要實現替代IRequestChannel用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; 
} 

要使用上面的方法,你可以從配置文件中獲取兩個參數,或使用一些常數值:

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

,並按照通過其端口類型和消息它的路線,你會發現類型:

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

,從中可以構建XML負載的形狀的GetData:

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