Add unit tests to demonstrate resolving client dependencies automatically and supplyi...
[castle.git] / Facilities / Wcf / Castle.Facilities.WcfIntegration / WcfFacility.cs
blobadcc438919c424c0aa425b863154e0c375586bef
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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
17 using System;
18 using System.ServiceModel;
19 using System.ServiceModel.Description;
20 using Castle.Core;
21 using Castle.MicroKernel;
22 using Castle.MicroKernel.Facilities;
24 public class WcfFacility : AbstractFacility
26 private readonly WcfClientModel[] clientModels;
28 public WcfFacility()
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)
85 serviceHost.Close();
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);
102 return clientModel;
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);
119 return serviceModel;
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));
136 else
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);
154 serviceHost.Open();
155 return serviceHost;
158 private void ValidateClientModel(WcfClientModel clientModel, ComponentModel componentModel)
160 Type contract;
162 if (componentModel != null)
164 contract = componentModel.Service;
166 else if (clientModel.Contract != null)
168 contract = clientModel.Contract;
170 else
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.");
221 else
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