概述
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 接口:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124using
System.Collections.Generic;
using
System.ServiceModel;
using
Model;
[ServiceContract]
public
interface
IDICOMService
{
/// <summary>
/// Get patient identifier list by query condition
/// </summary>
/// <param name="patientQueryCondition"></param>
/// <returns></returns>
[OperationContract]
List<PatientIdentifier> Query(PatientQueryCondition patientQueryCondition);
/// <summary>
/// Retrieve cache relate file path list
/// </summary>
/// <param name="patientID">patientID</param>
/// <param name="studyInstanceUID">studyInstanceUID</param>
/// <param name="seriesInstanceUID">seriesInstanceUID</param>
/// <param name="sopInstanceUID">sopInstanceUID</param>
/// <returns>cache relate file path list</returns>
[OperationContract]
List<
string
> Retrieve(
string
patientID,
string
studyInstanceUID,
string
seriesInstanceUID,
string
sopInstanceUID);
/// <summary>
/// Retrieve file stream by cache related file path
/// </summary>
/// <param name="relatedFilePath">related file path</param>
/// <returns>file stream bytes</returns>
[OperationContract]
byte
[] RetrieveFileStream(
string
relatedFilePath);
/// <summary>
/// Retrieve file name and file byte stream list
/// </summary>
/// <param name="patientID">patientID</param>
/// <param name="studyInstanceUID">studyInstanceUID</param>
/// <param name="seriesInstanceUID">seriesInstanceUID</param>
/// <param name="sopInstanceUID">sopInstanceUID</param>
/// <returns>file name and file byte stream list </returns>
[OperationContract]
Dictionary<
string
,
byte
[]> RetrieveFileNameAndStream(
string
patientID,
string
studyInstanceUID,
string
seriesInstanceUID,
string
sopInstanceUID);
/// <summary>
/// Retrieve file stream by sort and paging
/// </summary>
/// <param name="patientID">patientID</param>
/// <param name="studyInstanceUID">studyInstanceUID</param>
/// <param name="seriesInstanceUID">seriesInstanceUID</param>
/// <param name="sopInstanceUID">sopInstanceUID</param>
/// <param name="page">page</param>
/// <param name="count">count</param>
/// <param name="sort">sort</param>
/// <param name="sequence">sequence</param>
/// <returns>file name and file byte stream list </returns>
[OperationContract]
Dictionary<
string
,
byte
[]> RetrieveFileStreamBySortAndPaging(
string
patientID,
string
studyInstanceUID,
string
seriesInstanceUID,
string
sopInstanceUID,
int
page,
int
count,
string
sort,
string
sequence);
/// <summary>
/// Retrieve DicomFileResult entity list By Condition
/// </summary>
/// <param name="patientID">patientID</param>
/// <param name="studyInstanceUID">studyInstanceUID</param>
/// <param name="seriesInstanceUID">seriesInstanceUID</param>
/// <param name="sopInstanceUID">sopInstanceUID</param>
/// <returns>DicomFileResult entity list</returns>
[OperationContract]
List<DicomFileResult> RetrieveDicomFileResultListByCondition(
string
patientID,
string
studyInstanceUID,
string
seriesInstanceUID,
string
sopInstanceUID);
/// <summary>
/// Retrieve DicomFileResult entity List by sort and paging
/// </summary>
/// <param name="patientID">patientID</param>
/// <param name="studyInstanceUID">studyInstanceUID</param>
/// <param name="seriesInstanceUID">seriesInstanceUID</param>
/// <param name="sopInstanceUID">sopInstanceUID</param>
/// <param name="page">page</param>
/// <param name="count">count</param>
/// <param name="sort">sort</param>
/// <param name="sequence">sequence</param>
/// <returns>file name and file byte stream list </returns>
[OperationContract]
List<DicomFileResult> RetrieveDicomFileResultListBySortAndPaging(
string
patientID,
string
studyInstanceUID,
string
seriesInstanceUID,
string
sopInstanceUID,
int
page,
int
count,
string
sort,
string
sequence);
/// <summary>
/// Retrieve Report file byte stream by encount type and activity state
/// </summary>
/// <param name="encountType">encount type</param>
/// <param name="activityState">activity state</param>
/// <returns>file byte stream</returns>
[OperationContract]
byte
[] RetrieveReportFileByCondition(
string
encountType,
string
activityState);
/// <summary>
/// Add Report File By encount type and activity state and byte stream
/// </summary>
/// <param name="encountType">encount Type</param>
/// <param name="activityState">activity State</param>
/// <param name="byteStream">report file byte stream</param>
/// <returns>the result is true or false</returns>
[OperationContract]
bool
AddReportFile(
string
encountType,
string
activityState,
byte
[] byteStream);
/// <summary>
/// Remove Report file by encount type and activity state
/// </summary>
/// <param name="encountType">encount Type</param>
/// <param name="activityState">activity State</param>
/// <returns>the result is true or false</returns>
[OperationContract]
bool
RemoveReportFileByCondition(
string
encountType,
string
activityState);
}
接下来实现接口
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152using
System.Collections.Generic;
using
DAL;
using
IDAL;
using
Model;
using
System.ServiceModel;
/// <summary>
/// Dicom Service class
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public
class
DICOMService : IDICOMService
{
#region Private Methods
#endregion
#region IDICOMService Members
/// <summary>
/// Query DICOM server by PatientQueryCondition entity
/// </summary>
/// <param name="patientQueryCondition">PatientQueryCondition entity </param>
/// <returns>Patient Identifier list</returns>
public
List<PatientIdentifier> Query(PatientQueryCondition patientQueryCondition)
{
return
DICOMServiceHandle.Instance.Query(patientQueryCondition);
}
/// <summary>
/// Retrieve cache relate file path list
/// </summary>
/// <param name="patientID">patientID</param>
/// <param name="studyInstanceUID">studyInstanceUID</param>
/// <param name="seriesInstanceUID">seriesInstanceUID</param>
/// <param name="sopInstanceUID">sopInstanceUID</param>
/// <returns>cache relate file path list</returns>
public
List<
string
> Retrieve(
string
patientID,
string
studyInstanceUID,
string
seriesInstanceUID,
string
sopInstanceUID)
{
return
DICOMServiceHandle.Instance.Retrieve(patientID, studyInstanceUID, seriesInstanceUID, sopInstanceUID);
}
/// <summary>
/// Retrieve file stream by cache related file path
/// </summary>
/// <param name="relatedfilePath"> cache related file path</param>
/// <returns>file stream bytes</returns>
public
byte
[] RetrieveFileStream(
string
relatedfilePath)
{
return
DICOMServiceHandle.Instance.RetrieveFileStream(relatedfilePath);
}
/// <summary>
/// Retrieve file name and file byte stream List
/// </summary>
/// <param name="patientID">patientID</param>
/// <param name="studyInstanceUID">studyInstanceUID</param>
/// <param name="seriesInstanceUID">seriesInstanceUID</param>
/// <param name="sopInstanceUID">sopInstanceUID</param>
/// <returns>file name and file byte stream List</returns>
public
Dictionary<
string
,
byte
[]> RetrieveFileNameAndStream(
string
patientID,
string
studyInstanceUID,
string
seriesInstanceUID,
string
sopInstanceUID)
{
return
DICOMServiceHandle.Instance.RetrieveFileStream(patientID, studyInstanceUID, seriesInstanceUID,
sopInstanceUID);
}
/// <summary>
/// Retrieve DicomFileResult entity list By Condition
/// </summary>
/// <param name="patientID">patientID</param>
/// <param name="studyInstanceUID">studyInstanceUID</param>
/// <param name="seriesInstanceUID">seriesInstanceUID</param>
/// <param name="sopInstanceUID">sopInstanceUID</param>
/// <returns>DicomFileResult entity list</returns>
public
List<DicomFileResult> RetrieveDicomFileResultListByCondition(
string
patientID,
string
studyInstanceUID,
string
seriesInstanceUID,
string
sopInstanceUID)
{
return
DICOMServiceHandle.Instance.RetrieveDcmFileResultListByCondition(patientID, studyInstanceUID,
seriesInstanceUID, sopInstanceUID);
}
/// <summary>
/// Retrieve DicomFileResult entity List By condition
/// </summary>
/// <param name="patientID">patientID</param>
/// <param name="studyInstanceUID">studyInstanceUID</param>
/// <param name="seriesInstanceUID">seriesInstanceUID</param>
/// <param name="sopInstanceUID">sopInstanceUID</param>
/// <param name="page">page</param>
/// <param name="count">count</param>
/// <param name="sort">sort</param>
/// <param name="sequence">sequence</param>
/// <returns>DicomFileResult entity list</returns>
public
List<DicomFileResult> RetrieveDicomFileResultListBySortAndPaging(
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);
}
/// <summary>
/// Retrieve report file stream by encount type and activity state
/// </summary>
/// <param name="encountType">encount type</param>
/// <param name="activityState">activity state</param>
/// <returns>report file byte stream</returns>
public
byte
[] RetrieveReportFileByCondition(
string
encountType,
string
activityState)
{
return
DICOMServiceHandle.Instance.RetrieveReportFileByCondition(encountType, activityState);
}
/// <summary>
/// Add report file by encount type and activity state and byte stream
/// </summary>
/// <param name="encountType">encount type</param>
/// <param name="activityState">activity state</param>
/// <param name="byteStream">byte stream</param>
/// <returns>the result is true or false</returns>
public
bool
AddReportFile(
string
encountType,
string
activityState,
byte
[] byteStream)
{
return
DICOMServiceHandle.Instance.AddReportFile(encountType, activityState, byteStream);
}
/// <summary>
/// Remove report file by encount type and activity state
/// </summary>
/// <param name="encountType">encount type</param>
/// <param name="activityState">activity state</param>
/// <returns>the result is true or false</returns>
public
bool
RemoveReportFileByCondition(
string
encountType,
string
activityState)
{
return
DICOMServiceHandle.Instance.RemoveReportFile(encountType, activityState);
}
/// <summary>
/// Retrieve file stream by sort and paging
/// </summary>
/// <param name="patientID">patientID</param>
/// <param name="studyInstanceUID">studyInstanceUID</param>
/// <param name="seriesInstanceUID">seriesInstanceUID</param>
/// <param name="sopInstanceUID">sopInstanceUID</param>
/// <param name="page">page</param>
/// <param name="count">count</param>
/// <param name="sort">sort</param>
/// <param name="sequence">sequence</param>
/// <returns>file name and file byte stream list</returns>
public
Dictionary<
string
,
byte
[]> RetrieveFileStreamBySortAndPaging(
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
}
其中
1[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
是保证WCF实例是单例的.
然后再如下在运行窗口把这个给启动了.
123456789101112131415161718192021222324252627282930313233class
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配置如下:
12345678910111213141516171819202122232425<system.serviceModel>
<bindings/>
<client/>
<services>
<service name=
"DICOMServiceLib.BLL.DICOMService"
behaviorConfiguration=
"DICOMServiceMEXBehavior"
>
<endpoint address=
""
binding=
"basicHttpBinding"
contract=
"DICOMServiceLib.IDAL.IDICOMService"
/>
<!-- Enable the MEX endpoint -->
<endpoint address=
"mex"
binding=
"mexHttpBinding"
contract=
"IMetadataExchange"
/>
<!-- Need to add
this
so MEX knows the address of our service -->
<host>
<baseAddresses>
</baseAddresses>
</host>
</service>
</services>
<!-- A behavior definition
for
MEX -->
<behaviors>
<serviceBehaviors>
<behavior name=
"DICOMServiceMEXBehavior"
>
<serviceMetadata httpGetEnabled=
"true"
/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
运行的结果如下图:
欢迎各位参与讨论,如果觉得对你有帮助,请点击 推荐下,万分谢谢.
作者:spring yang
出处:http://www.cnblogs.com/springyangwc/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。