欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解WCF服務(wù)中的svc文件

 更新時間:2022年03月04日 09:49:38   作者:.NET開發(fā)菜鳥  
本文詳細(xì)講解了WCF服務(wù)中的svc文件,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

一、新建一個WCF服務(wù)應(yīng)用程序:

文件->新建->項目:選擇WCF下面的WCF服務(wù)應(yīng)用程序

二、分析WcfSvcDemo項目,該項目的結(jié)構(gòu)如下:

在該項目中,會默認(rèn)生成一個IService1.cs的文件和Service1.svc文件。Service1.svc文件封裝的就是提供給客戶端的服務(wù)引用。
首先查看IService1.cs文件,從名字上面就可以看出這是一個接口文件,里面定義了一個接口IService1,接口上面使用了ServiceContract,意思是把這個接口聲明為服務(wù)契約,服務(wù)契約是對客戶端而言的,就是這個接口可以暴露出來讓客戶端可以看見。接口里面定義了兩個方法,每個方法上面都使用了[OperationContract],意思是把這兩個方法聲明為操作契約。只有把接口里面的方法聲明為操作契約,在客戶端里面才可以看到相應(yīng)的方法,否則在客戶端里面看不到在接口里面定義的方法。

在來看Service.svc文件,可以看到下面有一個Service.svc.cs文件,這個文件里面定義了一個繼承IService1接口的類Service1,并實(shí)現(xiàn)了IService1接口里面的方法。

刪除Service.svc.cs文件,可以查看Service.svc文件,該文件里面就一行代碼;

<%@ ServiceHost Language="C#" Debug="true" Service="WcfSvcDemo.Service1" CodeBehind="Service1.svc.cs" %>

這里面有兩個重要的參數(shù):Service和CodeBehind。Service是屬性值是WCF的服務(wù)實(shí)現(xiàn)類的完全限定名。CodeBehind是服務(wù)實(shí)現(xiàn)類所在的文件名。在運(yùn)行的時候,宿主程序從svc文件中的Service屬性得到WCF服務(wù)的完全限定名,然后從配置文件中找到同名的servicce,進(jìn)而找到所有的EndPoint,并根據(jù)其屬性進(jìn)行實(shí)例化。
配置文件中的Service名字必須是Service類名的完全限定名(即Namespace.classname),EndPoint的Contract必須是Service接口的完全限定名。否則,程序就無法從程序集中找到相應(yīng)的類進(jìn)行加載。
注意:如果要修改接口實(shí)現(xiàn)類的名稱,必須使用“重構(gòu)”的方式進(jìn)行修改,因?yàn)橹挥欣?ldquo;重構(gòu)”的方式修改Servie類名的時候,.svc文件里面Service的屬性值才會被修改,利用其它方式修改類名,.svc文件里面Service的屬性值會保留原值,這樣在運(yùn)行的時候,根據(jù)svc里面Service的屬性值查找不到相應(yīng)的類,程序就會報錯。

svc文件里面還有一個重要的參數(shù):ServiceHostFactory。ServiceHostFactory旨在解決從IIS或WAS中訪問自定義ServiceHost的問題。因?yàn)閺腟erviceHost派生的自定義宿主是動態(tài)配置的并且可能為各種類型,所以宿主環(huán)境從不會直接將其實(shí)例化。相反,WCF使用工廠模式提供宿主環(huán)境和服務(wù)的具體類型之間的間接層。除非進(jìn)行通知,否則它使用返回ServiceHost的實(shí)例的ServiceHostFactory的默認(rèn)實(shí)現(xiàn)。(在新建的svc文件中默認(rèn)實(shí)現(xiàn)就是CodeBehind屬性的值)。但也可以通過在@ServiceHost指令中指定工廠實(shí)現(xiàn)的CLR類型名稱來提供自己的工廠(用于返回派生宿主)。

下面是用于返回派生的ServiceHost的自定義ServiceHostFactory:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace Public.CustomService
{
    public class CustomServiceHostFactory : ServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            CustomServiceHost customServiceHost = new CustomServiceHost(serviceType, baseAddresses);
            return customServiceHost;
        }
    }
}

其中CustomServiceHost是自定義的繼承自ServiceHost的類,用于讀取配置文件的配置,CustomServiceHost類的定義如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace Public.CustomService
{
    public class CustomServiceHost :ServiceHost
    {
        public CustomServiceHost(Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            //加載Web.config的配置
            log4net.Config.XmlConfigurator.Configure();
        }
        protected override void ApplyConfiguration()
        {
            base.ApplyConfiguration();
        }
    }
}

若要使用此工廠,而不使用默認(rèn)工廠,則應(yīng)該在@ServiceHost指令中提供相應(yīng)的類型名稱:

<%@ ServiceHost  Service="CustomSvcDemo.DatabaseService" Factory="Public.CustomService.CustomServiceHostFactory"  %>

其中Service是實(shí)現(xiàn)類的完全限定名,F(xiàn)actory是自定義ServiceHostFactory的完全限定名,Public是一個dll文件。

若要使用此工廠,而不使用默認(rèn)工廠,則應(yīng)該在@ServiceHost指令中提供相應(yīng)的類型名稱:
盡管對于從CreateServiceHost返回的ServiceHost可以執(zhí)行什么操作沒有技術(shù)限制,但建議您盡可能使工廠實(shí)現(xiàn)簡單化。如果有大量的自定義邏輯,最好將這些邏輯放入宿主內(nèi)而不是工廠內(nèi),以便可以重用它們。
應(yīng)在這里提及另一個承載API的層。WCF還具有ServiceHostBase和ServiceHostFactoryBase,可從中分別派生ServiceHost和ServiceHostFactory。對于您必須通過自己的自定義創(chuàng)建來交換元數(shù)據(jù)系統(tǒng)的大型組件的更高級方案,存在上述這些特性。

下面通過兩個具體的示例程序分別實(shí)現(xiàn)上面描述的默認(rèn)工廠和自定義工廠。

三、使用默認(rèn)工廠方式

1、刪除新建項目時自動創(chuàng)建的IService1.cs和Service1.svc文件,然后添加一個svc文件,在項目上面右鍵->添加->新建項:

2、在新建項里面選擇web里面的WCF服務(wù),命名為MyService:

3、點(diǎn)“添加”,除了創(chuàng)建MyService.svc文件以外,還會自動創(chuàng)建一個名為IMyService.cs的接口文件,MyService.svc.cs里面的MyService默認(rèn)實(shí)現(xiàn)IMyService接口.

刪除IMyService接口里面自動生成的方法,添加一個GetCurrentTime的方法,用來返回當(dāng)前的時間,IMyService接口定義如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WcfSvcDemo
{
    // 注意: 使用“重構(gòu)”菜單上的“重命名”命令,可以同時更改代碼和配置文件中的接口名“IMyService”。
    [ServiceContract]
    public interface IMyService
    {
        /// <summary>
        /// 獲取當(dāng)前時間
        /// </summary>
        /// <returns></returns>
        [OperationContract]
        DateTime GetCurrentTime();
    }
}

4、MyService.svc.cs里面的MyService類實(shí)現(xiàn)IMyService接口,MyService類定義如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WcfSvcDemo
{
    // 注意: 使用“重構(gòu)”菜單上的“重命名”命令,可以同時更改代碼、svc 和配置文件中的類名“MyService”。
    // 注意: 為了啟動 WCF 測試客戶端以測試此服務(wù),請在解決方案資源管理器中選擇 MyService.svc 或 MyService.svc.cs,然后開始調(diào)試。
    public class MyService : IMyService
    {
        /// <summary>
        /// 返回當(dāng)前時間
        /// </summary>
        /// <returns></returns>
        public DateTime GetCurrentTime()
        {
            return DateTime.Now;
        }
    }
}

5、修改配置文件,增加service、binding等節(jié)點(diǎn),修改后的配置文件如下:

<?xml version="1.0"?>
<configuration>
  <appSettings/>
  <system.web>
    <compilation debug="true" targetFramework="4.0"/>
    <httpRuntime/>
  </system.web>
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="metadataBehavior" name="WcfSvcDemo.MyService">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="Contract" name="MyService" contract="WcfSvcDemo.IMyService"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <!-- 為避免泄漏元數(shù)據(jù)信息,請在部署前將以下值設(shè)置為 false -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!-- 要接收故障異常詳細(xì)信息以進(jìn)行調(diào)試,請將以下值設(shè)置為 true。在部署前設(shè)置為 false 以避免泄漏異常信息 -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="Contract" closeTimeout="00:00:05" openTimeout="00:00:05" receiveTimeout="11:00:00" sendTimeout="11:00:00" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" transferMode="Buffered">
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
        </binding>
      </basicHttpBinding>
    </bindings>
    <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        若要在調(diào)試過程中瀏覽 Web 應(yīng)用程序根目錄,請將下面的值設(shè)置為 True。
        在部署之前將該值設(shè)置為 False 可避免泄露 Web 應(yīng)用程序文件夾信息。
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

主要是修改service節(jié)點(diǎn)里面的name是服務(wù)實(shí)現(xiàn)類的完全限定名,contract是服務(wù)接口的完全限定名。

6、把WCF服務(wù)部署到IIS上面

在IIS上面網(wǎng)站->添加網(wǎng)站:

配置網(wǎng)站名稱、路徑、IP地址和端口:

網(wǎng)站配置完成以后,瀏覽.svc文件,驗(yàn)證網(wǎng)站是否配置成功,如出現(xiàn)下面的截圖,說明網(wǎng)站配置成功:

7、創(chuàng)建代理類

客戶端引用WCF的時候一般是靜態(tài)引用,直接添加服務(wù)引用,這種方式如果IP地址和端口號變了,需要用代碼重新編譯然后在部署,這樣不方便。這里使用svcutil代理類的方式進(jìn)行客戶端的調(diào)用。

使用svcutil生成代理類:

新建一個項目,選擇類庫項目,把剛才生成的類文件添加到類庫項目中,項目結(jié)構(gòu)如下:

在類庫項目中新添加一個類,命名為:MyServiceProxy,使用這個類來調(diào)用代理類,MyServiceProxy類的定義如下:

using Public.ConfigBinding;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace MyProxyService
{
    public class MyServiceProxy
    {
        private static MyServiceClient _databaseService;

        private static MyServiceClient DatabaseService
        {
            get
            {
                if (_databaseService == null)
                {
                    string sApServer1 = ConfigurationManager.AppSettings["ApServer1"];

                    if (sApServer1 == null)
                    {
                        _databaseService = new MyServiceClient();
                    }
                    else
                    {
                        EndpointAddress endPointAddr = new EndpointAddress(string.Format("{0}/MyService.svc", sApServer1));
                        _databaseService = new MyServiceClient(HttpBinding.BasicHttpBinding, endPointAddr);
                    }
                }

                if (_databaseService.State == CommunicationState.Faulted)
                {
                    string sApServer2 = ConfigurationManager.AppSettings["ApServer2"];

                    if (sApServer2 == null)
                    {
                        _databaseService = new MyServiceClient();
                    }
                    else
                    {
                        EndpointAddress endPointAddr = new EndpointAddress(string.Format("{0}/MyService.svc", sApServer2));
                        _databaseService = new MyServiceClient(HttpBinding.BasicHttpBinding, endPointAddr);
                    }
                }

                return _databaseService;
            }
        }

        /// <summary>
        /// 返回當(dāng)前時間
        /// </summary>
        /// <returns></returns>
        public static DateTime GetCurrentTime()
        {
            return DatabaseService.GetCurrentTime();
        }
    }
}

ApServer1和ApServer2是在配置文件中配置的IP地址和端口號,這樣如果IP地址和端口號變了,只需要修改配置文件就可以。

GetCurrentTime()方法是調(diào)用的代理類里面的方法,把該方法定義為靜態(tài)方法。

8、創(chuàng)建客戶端調(diào)用

在解決方案中,新建一個winform程序,界面上面只有一個button按鈕,點(diǎn)擊按鈕,彈出當(dāng)前時間。需要添加對MyProxyService.dll文件的引用,在配置文件中增加ApServer1和ApServer2兩個節(jié)點(diǎn),配置文件如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="ApServer1" value="http://127.0.0.1:8090"/>
    <add key="ApServer2" value="http://127.0.0.1:8090"/>
  </appSettings>
  <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
    </startup>
</configuration>

button按鈕事件代碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MyProxyService;

namespace WinformClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btn_CurrentTime_Click(object sender, EventArgs e)
        {
            DateTime dtNow = MyServiceProxy.GetCurrentTime();
            MessageBox.Show("當(dāng)前時間:" + dtNow.ToString());
        }
    }
}

點(diǎn)擊按鈕后,運(yùn)行結(jié)果如下:

四、使用自定義工廠的方式

1、新添加一個WCF服務(wù),命名為CustomService,把默認(rèn)生成的CustomService.svc.cs文件刪掉,重新添加一個類:CustomService,該類繼承自生成的ICustomService接口,項目結(jié)構(gòu)如下:

修改CustomService.svc文件:

<%@ ServiceHost  Service="WcfSvcDemo.CustomService" Factory="Public.CustomService.CustomServiceHostFactory" %>

CustomServiceHostFactory是在另外的Public.dll里面創(chuàng)建的工廠類,用來返回ServiceHost,Public.dll的項目結(jié)構(gòu)如下:

CustomServiceHost類繼承自ServiceHost類,代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace Public.CustomService
{
    public class CustomServiceHost :ServiceHost
    {
        public CustomServiceHost(Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            //加載Web.config的配置
            log4net.Config.XmlConfigurator.Configure();
        }
        protected override void ApplyConfiguration()
        {
            base.ApplyConfiguration();
        }
    }
}

CustomServiceHostFactory是工廠類,繼承自ServiceHostFactory,用來返回ServiceHost,代碼如下;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace Public.CustomService
{
    public class CustomServiceHostFactory : ServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            CustomServiceHost customServiceHost = new CustomServiceHost(serviceType, baseAddresses);
            return customServiceHost;
        }
    }
}

HttpBinding代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace Public.ConfigBinding
{
    public class HttpBinding
    {
        private static BasicHttpBinding _BasicHttpBinding;

        public static BasicHttpBinding BasicHttpBinding
        {
            get
            {
                if (_BasicHttpBinding == null)
                {
                    _BasicHttpBinding = new BasicHttpBinding();

                    // 接收的訊息大小上限,默認(rèn)值為65,536字節(jié),
                    // 目前設(shè)定1k * 512,如果資料量大于這個值,請?zhí)岢鲇懻?,ex:8000筆資料大概128k
                    _BasicHttpBinding.MaxReceivedMessageSize = 400 * 8192 * 512;

                    // 由于回傳String長度過長在反串行化時會出錯!
                    // 所以放大最大字符串長度
                    _BasicHttpBinding.ReaderQuotas.MaxStringContentLength = 8192 * 1022;
                    _BasicHttpBinding.ReaderQuotas.MaxArrayLength = 8192 * 1022;
                    _BasicHttpBinding.SendTimeout = new TimeSpan(0, 5, 0);

                }

                return _BasicHttpBinding;
            }
        }
    }
}

把CustomService.svc部署到IIS上面、創(chuàng)建代理類的方法、客戶端調(diào)用和默認(rèn)工廠里面的方法一樣,此處不在描述。

項目代碼下載路徑:下載地址

到此這篇關(guān)于WCF服務(wù)中svc文件詳解的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論