概述
Windows Communication Foundation (WCF) 是.NET Framework 的扩展,用来创建互连的系统。WCF 提供了创建安全的、可靠的、事务服务的统一框架,WCF 整合和扩展了现有分布式系统的开发技术,如Microsoft .Net Remoting、Web Services、Web Services Enhancements (WSE)等等,来开发统一的可靠系统。WCF 框架可以实现SOA架构的松散耦合的应用程序,WCF 简化了构建SOA架构应用的工作,同时通过统一Enterprise Services、Messaging、.Net Remoting、Web Services、WSE 等技术,降低开发复杂度。WCF服务可以通过属性Attribute进行配置,提高灵活性和效率,支持大量的Web Services标准,如XML、XSD、SOAP、Xpath、WSDL等标准和规范,如WS-Addressing、WS-Policy、WS- Security、WS-Trust、WS-Secure、WS-Reliable Messaging、WS-Atomic Transaction、WS-Coordination等等。
Windows communication Foundation (WCF) 框架模型
WCF组成结构
Service Class:一个标记了[ServiceContract]属性的类,在其中可能包含多个方法。除了标记了一些WCF 特有的Attribute 外,这个类与一般的类没有什么区别。
Host(宿主):可以是应用程序,进程如Windows Service 等,它是WCF Service 运行环境。 Endpoints:可以是一个,也可以是一组,它是WCF 实现通信的核心要素。在后面的实例应用中,我还会提到上面这三个概念。
(1)绑定:指定该端点如何与外界通信,也就是为端点指定通信协议。
传输协议:端点和客户端通过传输协议通信。比较常用的是HTTP和TCP。 编码协议:在进入通信链路之前,端点和客户通过编码协议对通信进行编码。比较常见的是XML文件二进制码。 安全协议:端点和用户通过安全协议保证通信的安全。比如一些敏感的信息,要求通过加密的传输信道。比较常见的是HTTPS和WS-Security。
(2)地址:一个端点地址指定端点的位置,如果通过端点与WCF通信,必须把通信指定到网络地址。
(3)契约:一个端点上契约指定通过该端点的用户能访问到WCF服务的什么操作。
在WCF 中,类ServiceEndpoint 代表了一个端点(Endpoint),在类中包含的EndpointAddress,Binding,ContractDescription 类型分别对应端点的地址,绑定和契约。
WCF服务模型
最后简单的说下WCF的服务模型。
WCF是一个层次架构,该架构的顶层称为服务模型,用于WCF服务的建模。
WCF服务模型提供了3种重要手段对自己的WCF服务进行建模:
(1)面向属性编程:WCF服务模型带有一套元数据属性,可以通过属性表示相应的实体,如:属性,接口,类等。
(2)面向配置编程:WCF服务模型带有方便的配置语言,可以通过它在配置文件中进行建模。
(3)常规命令编程:WCF服务模型带有一组方便的托管类,可以使用这些托管类对服务进行建模。
示例
定义Server 接口:
using System.Collections.Generic; using System.ServiceModel; using Model; [ServiceContract] public interface IDICOMService { ////// Get patient identifier list by query condition /// /// ///[OperationContract] List Query(PatientQueryCondition patientQueryCondition); /// /// Retrieve cache relate file path list /// /// patientID /// studyInstanceUID /// seriesInstanceUID /// sopInstanceUID ///cache relate file path list [OperationContract] ListRetrieve(string patientID, string studyInstanceUID, string seriesInstanceUID, string sopInstanceUID); /// /// Retrieve file stream by cache related file path /// /// related file path ///file stream bytes [OperationContract] byte[] RetrieveFileStream(string relatedFilePath); ////// Retrieve file name and file byte stream list /// /// patientID /// studyInstanceUID /// seriesInstanceUID /// sopInstanceUID ///file name and file byte stream list [OperationContract] DictionaryRetrieveFileNameAndStream(string patientID, string studyInstanceUID, string seriesInstanceUID, string sopInstanceUID); /// /// Retrieve file stream by sort and paging /// /// patientID /// studyInstanceUID /// seriesInstanceUID /// sopInstanceUID /// page /// count /// sort /// sequence ///file name and file byte stream list [OperationContract] DictionaryRetrieveFileStreamBySortAndPaging(string patientID, string studyInstanceUID, string seriesInstanceUID, string sopInstanceUID, int page, int count, string sort, string sequence); /// /// Retrieve DicomFileResult entity list By Condition /// /// patientID /// studyInstanceUID /// seriesInstanceUID /// sopInstanceUID ///DicomFileResult entity list [OperationContract] ListRetrieveDicomFileResultListByCondition(string patientID, string studyInstanceUID, string seriesInstanceUID, string sopInstanceUID); /// /// Retrieve DicomFileResult entity List by sort and paging /// /// patientID /// studyInstanceUID /// seriesInstanceUID /// sopInstanceUID /// page /// count /// sort /// sequence ///file name and file byte stream list [OperationContract] ListRetrieveDicomFileResultListBySortAndPaging(string patientID, string studyInstanceUID, string seriesInstanceUID, string sopInstanceUID, int page, int count, string sort, string sequence); /// /// Retrieve Report file byte stream by encount type and activity state /// /// encount type /// activity state ///file byte stream [OperationContract] byte[] RetrieveReportFileByCondition(string encountType, string activityState); ////// Add Report File By encount type and activity state and byte stream /// /// encount Type /// activity State /// report file byte stream ///the result is true or false [OperationContract] bool AddReportFile(string encountType, string activityState, byte[] byteStream); ////// Remove Report file by encount type and activity state /// /// encount Type /// activity State ///the result is true or false [OperationContract] bool RemoveReportFileByCondition(string encountType, string activityState); }
接下来实现接口
using System.Collections.Generic; using DAL; using IDAL; using Model; using System.ServiceModel; ////// Dicom Service class /// [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class DICOMService : IDICOMService { #region Private Methods #endregion #region IDICOMService Members ////// Query DICOM server by PatientQueryCondition entity /// /// PatientQueryCondition entity ///Patient Identifier list public ListQuery(PatientQueryCondition patientQueryCondition) { return DICOMServiceHandle.Instance.Query(patientQueryCondition); } /// /// Retrieve cache relate file path list /// /// patientID /// studyInstanceUID /// seriesInstanceUID /// sopInstanceUID ///cache relate file path list public ListRetrieve(string patientID, string studyInstanceUID, string seriesInstanceUID, string sopInstanceUID) { return DICOMServiceHandle.Instance.Retrieve(patientID, studyInstanceUID, seriesInstanceUID, sopInstanceUID); } /// /// Retrieve file stream by cache related file path /// /// cache related file path ///file stream bytes public byte[] RetrieveFileStream(string relatedfilePath) { return DICOMServiceHandle.Instance.RetrieveFileStream(relatedfilePath); } ////// Retrieve file name and file byte stream List /// /// patientID /// studyInstanceUID /// seriesInstanceUID /// sopInstanceUID ///file name and file byte stream List public DictionaryRetrieveFileNameAndStream(string patientID, string studyInstanceUID, string seriesInstanceUID, string sopInstanceUID) { return DICOMServiceHandle.Instance.RetrieveFileStream(patientID, studyInstanceUID, seriesInstanceUID, sopInstanceUID); } /// /// Retrieve DicomFileResult entity list By Condition /// /// patientID /// studyInstanceUID /// seriesInstanceUID /// sopInstanceUID ///DicomFileResult entity list public ListRetrieveDicomFileResultListByCondition(string patientID, string studyInstanceUID, string seriesInstanceUID, string sopInstanceUID) { return DICOMServiceHandle.Instance.RetrieveDcmFileResultListByCondition(patientID, studyInstanceUID, seriesInstanceUID, sopInstanceUID); } /// /// Retrieve DicomFileResult entity List By condition /// /// patientID /// studyInstanceUID /// seriesInstanceUID /// sopInstanceUID /// page /// count /// sort /// sequence ///DicomFileResult entity list public ListRetrieveDicomFileResultListBySortAndPaging(string patientID, string studyInstanceUID, string seriesInstanceUID, string sopInstanceUID, int page, int count, string sort, string sequence) { return DICOMServiceHandle.Instance.RetrieveDcmFileResultListBySortAndPaging(patientID, studyInstanceUID, seriesInstanceUID, sopInstanceUID, page, count, sort, sequence); } /// /// Retrieve report file stream by encount type and activity state /// /// encount type /// activity state ///report file byte stream public byte[] RetrieveReportFileByCondition(string encountType, string activityState) { return DICOMServiceHandle.Instance.RetrieveReportFileByCondition(encountType, activityState); } ////// Add report file by encount type and activity state and byte stream /// /// encount type /// activity state /// byte stream ///the result is true or false public bool AddReportFile(string encountType, string activityState, byte[] byteStream) { return DICOMServiceHandle.Instance.AddReportFile(encountType, activityState, byteStream); } ////// Remove report file by encount type and activity state /// /// encount type /// activity state ///the result is true or false public bool RemoveReportFileByCondition(string encountType, string activityState) { return DICOMServiceHandle.Instance.RemoveReportFile(encountType, activityState); } ////// Retrieve file stream by sort and paging /// /// patientID /// studyInstanceUID /// seriesInstanceUID /// sopInstanceUID /// page /// count /// sort /// sequence ///file name and file byte stream list public DictionaryRetrieveFileStreamBySortAndPaging(string patientID, string studyInstanceUID, string seriesInstanceUID, string sopInstanceUID, int page, int count, string sort, string sequence) { return DICOMServiceHandle.Instance.RetrieveFileStreamBySortAndPaging(patientID, studyInstanceUID, seriesInstanceUID, sopInstanceUID, page, count, sort, sequence); } #endregion }
其中
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
是保证WCF实例是单例的.
然后再如下在运行窗口把这个给启动了.
class Program { [STAThread] static void Main(string[] args) { Console.WriteLine("***** Console Based Host*****"); var timer = new QueryDicomServerTimer(); using (ServiceHost serviceHost = new ServiceHost(typeof(DICOMService))) { serviceHost.Open(); Console.WriteLine("The server is ready."); DisplayServerInfo(serviceHost); timer.Start(); Console.WriteLine("Press the Enter key to terminate the service"); Console.ReadLine(); } timer.End(); } static void DisplayServerInfo(ServiceHost serviceHost) { Console.WriteLine(); Console.WriteLine("****** Host Info ******"); foreach (var endpoint in serviceHost.Description.Endpoints) { Console.WriteLine("The address is {0}", endpoint.Address); Console.WriteLine("The binding is {0}", endpoint.Binding.Name); Console.WriteLine("The contract is {0}", endpoint.Contract.Name); Console.WriteLine(); } Console.WriteLine("***********************"); } }
web.config配置如下:
运行的结果如下图:
欢迎各位参与讨论,如果觉得对你有帮助,请点击 推荐下,万分谢谢.
作者:
出处:
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。