概述
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)绑定:指定该端点如何与外界通信,也就是为端点指定通信协议。
(2)地址:一个端点地址指定端点的位置,如果通过端点与WCF通信,必须把通信指定到网络地址。
(3)契约:一个端点上契约指定通过该端点的用户能访问到WCF服务的什么操作。
在WCF 中,类ServiceEndpoint 代表了一个端点(Endpoint),在类中包含的EndpointAddress,Binding,ContractDescription 类型分别对应端点的地址,绑定和契约。
WCF服务模型
最后简单的说下WCF的服务模型。
WCF是一个层次架构,该架构的顶层称为服务模型,用于WCF服务的建模。
WCF服务模型提供了3种重要手段对自己的WCF服务进行建模:
(1)面向属性编程:WCF服务模型带有一套元数据属性,可以通过属性表示相应的实体,如:属性,接口,类等。
(2)面向配置编程:WCF服务模型带有方便的配置语言,可以通过它在配置文件中进行建模。
(3)常规命令编程:WCF服务模型带有一组方便的托管类,可以使用这些托管类对服务进行建模。
示例
定义Server 接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
using
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);
}
|
接下来实现接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
using
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实例是单例的.
然后再如下在运行窗口把这个给启动了.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
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配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。