1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.Facilities
.WcfIntegration
18 using System
.ServiceModel
;
19 using System
.ServiceModel
.Description
;
21 using Castle
.MicroKernel
;
22 using Castle
.MicroKernel
.Facilities
;
24 public class WcfFacility
: AbstractFacility
26 private readonly WcfClientModel
[] clientModels
;
32 public WcfFacility(params WcfClientModel
[] clientModels
)
34 foreach (WcfClientModel clientModel
in clientModels
)
36 ValidateClientModel(clientModel
, null);
38 this.clientModels
= clientModels
;
41 protected override void Init()
43 Kernel
.ComponentRegistered
+= Kernel_ComponentRegistered
;
44 Kernel
.ComponentUnregistered
+= Kernel_ComponentUnregistered
;
45 Kernel
.ComponentModelCreated
+= Kernel_ComponentModelCreated
;
47 if (clientModels
!= null && clientModels
.Length
> 0)
49 Kernel
.Resolver
.AddSubResolver(new WcfClientResolver(clientModels
));
53 private void Kernel_ComponentModelCreated(ComponentModel componentModel
)
55 WcfClientModel clientModel
= ResolveClientModel(componentModel
);
57 if (clientModel
!= null)
59 componentModel
.ExtendedProperties
[WcfConstants
.ClientModelKey
] = clientModel
;
60 componentModel
.CustomComponentActivator
= typeof(WcfClientActivator
);
61 componentModel
.LifestyleType
= LifestyleType
.Transient
;
65 private void Kernel_ComponentRegistered(string key
, IHandler handler
)
67 ComponentModel componentModel
= handler
.ComponentModel
;
68 WcfServiceModel serviceModel
= ResolveServiceModel(componentModel
);
70 if (serviceModel
!= null)
72 WindsorServiceHost serviceHost
= CreateAndOpenServiceHost(serviceModel
, componentModel
);
73 componentModel
.ExtendedProperties
[WcfConstants
.ServiceHostKey
] = serviceHost
;
77 private void Kernel_ComponentUnregistered(string key
, IHandler handler
)
79 ComponentModel componentModel
= handler
.ComponentModel
;
80 ServiceHost serviceHost
=
81 componentModel
.ExtendedProperties
[WcfConstants
.ServiceHostKey
] as ServiceHost
;
83 if (serviceHost
!= null)
89 private WcfClientModel
ResolveClientModel(ComponentModel componentModel
)
91 WcfClientModel clientModel
= null;
93 if (componentModel
.Service
.IsInterface
)
95 if (WcfUtils
.FindDependency
<WcfClientModel
>(
96 componentModel
.CustomDependencies
, out clientModel
))
98 ValidateClientModel(clientModel
, componentModel
);
105 private WcfServiceModel
ResolveServiceModel(ComponentModel componentModel
)
107 WcfServiceModel serviceModel
= null;
109 if (componentModel
.Implementation
.IsClass
&&
110 !componentModel
.Implementation
.IsAbstract
)
112 if (WcfUtils
.FindDependency
<WcfServiceModel
>(
113 componentModel
.CustomDependencies
, out serviceModel
))
115 ValidateServiceModel(serviceModel
, componentModel
);
123 private void AddServiceEndpoint(WcfEndpoint endpoint
, WindsorServiceHost serviceHost
)
125 if (endpoint
.EndpointAddress
!= null)
127 ContractDescription contract
= ContractDescription
.GetContract(endpoint
.Contract
);
128 serviceHost
.Description
.Endpoints
.Add(
129 new ServiceEndpoint(contract
, endpoint
.Binding
, endpoint
.EndpointAddress
));
131 else if (!string.IsNullOrEmpty(endpoint
.Via
))
133 serviceHost
.AddServiceEndpoint(endpoint
.Contract
, endpoint
.Binding
,
134 endpoint
.Address
, new Uri(endpoint
.Via
));
138 serviceHost
.AddServiceEndpoint(
139 endpoint
.Contract
, endpoint
.Binding
, endpoint
.Address
);
143 private WindsorServiceHost
CreateAndOpenServiceHost(WcfServiceModel serviceModel
,
144 ComponentModel componentModel
)
146 WindsorServiceHost serviceHost
= new WindsorServiceHost(
147 Kernel
, componentModel
.Implementation
, serviceModel
.GetBaseAddressesUris());
149 foreach (WcfEndpoint endpoint
in serviceModel
.Endpoints
)
151 AddServiceEndpoint(endpoint
, serviceHost
);
158 private void ValidateClientModel(WcfClientModel clientModel
, ComponentModel componentModel
)
162 if (componentModel
!= null)
164 contract
= componentModel
.Service
;
166 else if (clientModel
.Contract
!= null)
168 contract
= clientModel
.Contract
;
172 throw new FacilityException(
173 "The client endpoint does not specify a contract.");
176 if ((componentModel
!= null) && (clientModel
.Contract
!= null) &&
177 (clientModel
.Contract
!= componentModel
.Service
))
179 throw new FacilityException("The client endpoint contract " +
180 clientModel
.Contract
.FullName
+ " does not match the expected contaxt" +
181 componentModel
.Service
.FullName
+ ".");
184 clientModel
.Contract
= contract
;
186 if (string.IsNullOrEmpty(clientModel
.EndpointName
))
188 if (string.IsNullOrEmpty(clientModel
.Address
) && (clientModel
.EndpointAddress
== null))
190 throw new FacilityException("The client endpoint for contract " +
191 contract
.FullName
+ " does not specify an address.");
194 if (clientModel
.Binding
== null)
196 throw new FacilityException("The client endpoint for contract " +
197 contract
.FullName
+ " does not specify a binding.");
202 private void ValidateServiceModel(WcfServiceModel serviceModel
, ComponentModel componentModel
)
204 foreach (WcfEndpoint endpoint
in serviceModel
.Endpoints
)
206 Type contract
= endpoint
.Contract
;
208 if (contract
!= null)
210 if (!contract
.IsInterface
)
212 throw new FacilityException("The service endpoint contract " +
213 contract
.FullName
+ " does not represent an interface.");
216 else if (!componentModel
.Service
.IsInterface
)
218 throw new FacilityException(
219 "No service endpoint contract can be implied from the componnt.");
223 endpoint
.Contract
= componentModel
.Service
;
226 if (endpoint
.Binding
== null)
228 throw new FacilityException("The service endpoint for contract " +
229 endpoint
.Contract
.FullName
+ " does not specify a binding.");
232 if (endpoint
.Address
== null && endpoint
.EndpointAddress
== null)
234 endpoint
.Address
= string.Empty
; // Maybe has a base address