From 6684838ae608764f8105b6de282faa9d6513dbf6 Mon Sep 17 00:00:00 2001 From: cneuwirt Date: Mon, 7 Apr 2008 12:10:14 +0000 Subject: [PATCH] Support multiple WCF Service Models in addition to multiple endpoints per Service Model. git-svn-id: https://svn.castleproject.org/svn/castle/trunk@4992 73e77b4c-caa6-f847-a29a-24ab75ae54b6 --- .../ServiceHostFixture.cs | 34 ++++++++++++++ .../WcfClientFixture.cs | 3 +- .../Castle.Facilities.WcfIntegration-vs2008.csproj | 2 +- .../Client/WcfClientExtension.cs | 31 +++++++------ .../Client/WcfManagedChannelInterceptor.cs | 1 - .../WcfCommunicationDecommisionConcern.cs} | 10 ++--- .../Internal/WcfConstants.cs | 3 +- .../Internal/WcfUtils.cs | 33 ++++++-------- .../Service/WcfServiceExtension.cs | 52 +++++++++++++--------- .../Service/WindsorServiceHostFactory.cs | 28 +++++------- 10 files changed, 114 insertions(+), 83 deletions(-) rename Facilities/Wcf/Castle.Facilities.WcfIntegration/{Client/WcfChannelCleanupConcern.cs => Internal/WcfCommunicationDecommisionConcern.cs} (78%) diff --git a/Facilities/Wcf/Castle.Facilities.WcfIntegration.Tests/ServiceHostFixture.cs b/Facilities/Wcf/Castle.Facilities.WcfIntegration.Tests/ServiceHostFixture.cs index 87212f471..b41e44331 100644 --- a/Facilities/Wcf/Castle.Facilities.WcfIntegration.Tests/ServiceHostFixture.cs +++ b/Facilities/Wcf/Castle.Facilities.WcfIntegration.Tests/ServiceHostFixture.cs @@ -158,6 +158,40 @@ namespace Castle.Facilities.WcfIntegration.Tests } [Test] + public void CanCreateServiceHostAndOpenHostWithMultipleServiceModels() + { + using (new WindsorContainer() + .AddFacility() + .Register(Component.For() + .ImplementedBy() + .DependsOn(new { number = 42 }) + .ActAs( + new WcfServiceModel().AddEndpoints( + WcfEndpoint.BoundTo(new NetTcpBinding()) + .At("net.tcp://localhost/Operations") + ), + new WcfServiceModel() + .AddBaseAddresses( + "http://localhost:27198/UsingWindsor.svc") + .AddEndpoints( + WcfEndpoint.ForContract() + .BoundTo(new BasicHttpBinding()) + .At("Extended") + ) + ) + )) + { + IOperations client = ChannelFactory.CreateChannel( + new NetTcpBinding(), new EndpointAddress("net.tcp://localhost/Operations")); + Assert.AreEqual(42, client.GetValueFromConstructor()); + + IOperationsEx clientEx = ChannelFactory.CreateChannel( + new BasicHttpBinding(), new EndpointAddress("http://localhost:27198/UsingWindsor.svc/Extended")); + clientEx.Backup(new Dictionary()); + } + } + + [Test] public void WillApplyServiceScopedBehaviors() { CallCountServiceBehavior.CallCount = 0; diff --git a/Facilities/Wcf/Castle.Facilities.WcfIntegration.Tests/WcfClientFixture.cs b/Facilities/Wcf/Castle.Facilities.WcfIntegration.Tests/WcfClientFixture.cs index 0c2c75310..b47a9bcd8 100644 --- a/Facilities/Wcf/Castle.Facilities.WcfIntegration.Tests/WcfClientFixture.cs +++ b/Facilities/Wcf/Castle.Facilities.WcfIntegration.Tests/WcfClientFixture.cs @@ -63,8 +63,7 @@ namespace Castle.Facilities.WcfIntegration.Tests .At("net.tcp://localhost/Operations/Ex") ) ), - Component.For() - .ImplementedBy() + Component.For().ImplementedBy() .DependsOn(new { number = 42 }) .ActAs(new WcfServiceModel() ) diff --git a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Castle.Facilities.WcfIntegration-vs2008.csproj b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Castle.Facilities.WcfIntegration-vs2008.csproj index 1bc63d6aa..bf2a99a2d 100644 --- a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Castle.Facilities.WcfIntegration-vs2008.csproj +++ b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Castle.Facilities.WcfIntegration-vs2008.csproj @@ -84,7 +84,7 @@ - + diff --git a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfClientExtension.cs b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfClientExtension.cs index 914db2b7d..8f732ae86 100644 --- a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfClientExtension.cs +++ b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfClientExtension.cs @@ -51,7 +51,8 @@ namespace Castle.Facilities.WcfIntegration { model.CustomComponentActivator = typeof(WcfClientActivator); model.ExtendedProperties[WcfConstants.ClientModelKey] = clientModel; - model.LifecycleSteps.Add(LifecycleStepType.Decommission, WcfChannelCleanupConcern.Instance); + model.LifecycleSteps.Add(LifecycleStepType.Decommission, + WcfCommunicationDecomissionConcern.Instance); InstallManagedChannelInterceptor(model); } } @@ -85,26 +86,28 @@ namespace Castle.Facilities.WcfIntegration private IWcfClientModel ResolveClientModel(ComponentModel model) { - IWcfClientModel clientModel = null; if (model.Service.IsInterface) { - if (!WcfUtils.FindDependency( - model.CustomDependencies, out clientModel) && - model.Configuration != null) + foreach (IWcfClientModel clientModel in WcfUtils + .FindDependencies(model.CustomDependencies)) { - string endpointConfiguration = - model.Configuration.Attributes[WcfConstants.EndpointConfiguration]; - - if (!string.IsNullOrEmpty(endpointConfiguration)) - { - clientModel = new WcfClientModel( - WcfEndpoint.FromConfiguration(endpointConfiguration)); - } + return clientModel; } } - return clientModel; + if (model.Configuration != null) + { + string endpointConfiguration = + model.Configuration.Attributes[WcfConstants.EndpointConfiguration]; + + if (!string.IsNullOrEmpty(endpointConfiguration)) + { + return new WcfClientModel(WcfEndpoint.FromConfiguration(endpointConfiguration)); + } + } + + return null; } #region IDisposable Members diff --git a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfManagedChannelInterceptor.cs b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfManagedChannelInterceptor.cs index 4421c4103..5059e45d8 100644 --- a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfManagedChannelInterceptor.cs +++ b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfManagedChannelInterceptor.cs @@ -14,7 +14,6 @@ namespace Castle.Facilities.WcfIntegration { - using System.ServiceModel; using System.ServiceModel.Channels; using Castle.Core; using Castle.Core.Interceptor; diff --git a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfChannelCleanupConcern.cs b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfCommunicationDecommisionConcern.cs similarity index 78% rename from Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfChannelCleanupConcern.cs rename to Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfCommunicationDecommisionConcern.cs index d90dddeb0..ccc17fcd4 100644 --- a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Client/WcfChannelCleanupConcern.cs +++ b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfCommunicationDecommisionConcern.cs @@ -12,23 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -namespace Castle.Facilities.WcfIntegration +namespace Castle.Facilities.WcfIntegration.Internal { using System; using System.ServiceModel; using Castle.Core; using Castle.MicroKernel.LifecycleConcerns; - using Castle.Facilities.WcfIntegration.Internal; /// /// Ensure that the communication channel is properly disposed. /// [Serializable] - internal class WcfChannelCleanupConcern : ILifecycleConcern + internal class WcfCommunicationDecomissionConcern : ILifecycleConcern { - public static readonly WcfChannelCleanupConcern Instance = new WcfChannelCleanupConcern(); + public static readonly WcfCommunicationDecomissionConcern + Instance = new WcfCommunicationDecomissionConcern(); - protected WcfChannelCleanupConcern() + protected WcfCommunicationDecomissionConcern() { } diff --git a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfConstants.cs b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfConstants.cs index aa48ef45f..194a5be19 100644 --- a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfConstants.cs +++ b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfConstants.cs @@ -18,8 +18,7 @@ namespace Castle.Facilities.WcfIntegration { public const string BehaviorScopeKey = "scope"; - public const string ServiceModelKey = "wcf.serviceModel"; - public const string ServiceHostKey = "wcf.serviceHost"; + public const string ServiceHostsKey = "wcf.serviceHosts"; public const string ServiceHostEnabled = "wcfServiceHost"; public const string ClientModelKey = "wcf.clientModel"; diff --git a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfUtils.cs b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfUtils.cs index cdec13c21..ecec47a75 100644 --- a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfUtils.cs +++ b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Internal/WcfUtils.cs @@ -23,17 +23,19 @@ namespace Castle.Facilities.WcfIntegration.Internal internal static class WcfUtils { - public static bool FindDependency(IDictionary dependencies, - out T match) + public static bool IsHosted(IWcfServiceModel serviceModel) { - return FindDependency(dependencies, null, out match); + return serviceModel.IsHosted; } - public static bool FindDependency(IDictionary dependencies, - Predicate test, out T match) + public static IEnumerable FindDependencies(IDictionary dependencies) { - match = default(T); + return FindDependencies(dependencies, null); + } + public static IEnumerable FindDependencies(IDictionary dependencies, + Predicate test) + { foreach (object dependency in dependencies.Values) { if (dependency is T) @@ -42,25 +44,20 @@ namespace Castle.Facilities.WcfIntegration.Internal if (test == null || test(candidate)) { - match = candidate; - return true; + yield return candidate; } } } - return false; } - public static bool FindDependency(ICollection dependencies, - out T match) + public static IEnumerable FindDependencies(ICollection dependencies) { - return FindDependency(dependencies, null, out match); + return FindDependencies(dependencies, null); } - public static bool FindDependency(ICollection dependencies, - Predicate test, out T match) + public static IEnumerable FindDependencies(ICollection dependencies, + Predicate test) { - match = default(T); - foreach (object dependency in dependencies) { if (dependency is T) @@ -69,12 +66,10 @@ namespace Castle.Facilities.WcfIntegration.Internal if (test == null || test(candidate)) { - match = candidate; - return true; + yield return candidate; } } } - return false; } public static ICollection FindBehaviors(IKernel kernel, WcfBehaviorScope scope) diff --git a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Service/WcfServiceExtension.cs b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Service/WcfServiceExtension.cs index ad8c1af10..003bb9bef 100644 --- a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Service/WcfServiceExtension.cs +++ b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Service/WcfServiceExtension.cs @@ -61,7 +61,7 @@ namespace Castle.Facilities.WcfIntegration kernel.ComponentUnregistered += Kernel_ComponentUnregistered; } - WcfServiceExtension AddServiceHostBuilder() + public WcfServiceExtension AddServiceHostBuilder() where T : IServiceHostBuilder where M : IWcfServiceModel { @@ -71,30 +71,37 @@ namespace Castle.Facilities.WcfIntegration private void Kernel_ComponentRegistered(string key, IHandler handler) { + IList serviceHosts = null; ComponentModel model = handler.ComponentModel; - IWcfServiceModel serviceModel = ResolveServiceModel(model); - if (serviceModel != null) - { - model.ExtendedProperties[WcfConstants.ServiceModelKey] = serviceModel; + foreach (IWcfServiceModel serviceModel in ResolveServiceModels(model)) + { if (!serviceModel.IsHosted) { + serviceHosts = serviceHosts ?? new List(); ServiceHost serviceHost = CreateServiceHost(kernel, serviceModel, model); - model.ExtendedProperties[WcfConstants.ServiceHostKey] = serviceHost; + serviceHosts.Add(serviceHost); serviceHost.Open(); } } + + if (serviceHosts != null) + { + model.ExtendedProperties[WcfConstants.ServiceHostsKey] = serviceHosts; + } } private void Kernel_ComponentUnregistered(string key, IHandler handler) { - ComponentModel model = handler.ComponentModel; - ServiceHost serviceHost = - model.ExtendedProperties[WcfConstants.ServiceHostKey] as ServiceHost; + IList serviceHosts = handler.ComponentModel + .ExtendedProperties[WcfConstants.ServiceHostsKey] as IList; - if (serviceHost != null) + if (serviceHosts != null) { - serviceHost.Close(); + foreach (ServiceHost serviceHost in serviceHosts) + { + serviceHost.Close(); + } } } @@ -116,24 +123,25 @@ namespace Castle.Facilities.WcfIntegration } } - private IWcfServiceModel ResolveServiceModel(ComponentModel model) + private IEnumerable ResolveServiceModels(ComponentModel model) { - IWcfServiceModel serviceModel = null; + bool foundOne = false; if (model.Implementation.IsClass && !model.Implementation.IsAbstract) { - if (!WcfUtils.FindDependency( - model.CustomDependencies, out serviceModel) && - model.Configuration != null) + foreach (IWcfServiceModel serviceModel in + WcfUtils.FindDependencies(model.CustomDependencies)) { - if ("true" == model.Configuration.Attributes[WcfConstants.ServiceHostEnabled]) - { - serviceModel = new WcfServiceModel(); - } + foundOne = true; + yield return serviceModel; } - } - return serviceModel; + if (!foundOne && model.Configuration != null && + "true" == model.Configuration.Attributes[WcfConstants.ServiceHostEnabled]) + { + yield return new WcfServiceModel(); + } + } } #region CreateServiceHost Members diff --git a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Service/WindsorServiceHostFactory.cs b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Service/WindsorServiceHostFactory.cs index 5791715ea..4c8a299c1 100644 --- a/Facilities/Wcf/Castle.Facilities.WcfIntegration/Service/WindsorServiceHostFactory.cs +++ b/Facilities/Wcf/Castle.Facilities.WcfIntegration/Service/WindsorServiceHostFactory.cs @@ -19,6 +19,7 @@ namespace Castle.Facilities.WcfIntegration using System.ServiceModel.Activation; using Castle.Core; using Castle.MicroKernel; + using Castle.Facilities.WcfIntegration.Internal; public class WindsorServiceHostFactory : ServiceHostFactory where M : IWcfServiceModel @@ -64,36 +65,29 @@ namespace Castle.Facilities.WcfIntegration if (handler == null) { throw new InvalidOperationException( - string.Format("Could not find a component with {0} {1}, did you forget to register it?", + string.Format("Could not find a component with {0} {1}, did you forget to register it?", constructorStringType, constructorString)); } - ComponentModel componentModel = handler.ComponentModel; - IWcfServiceModel serviceModel = ObtainServiceModel(componentModel); - - if (serviceModel != null) - { - return WcfServiceExtension.CreateServiceHost(kernel, serviceModel, - componentModel, baseAddresses); - } - else + ComponentModel model = handler.ComponentModel; + foreach (IWcfServiceModel serviceModel in WcfUtils + .FindDependencies(model.CustomDependencies, + WcfUtils.IsHosted)) { - return ServiceHostBuilder.Build(handler.ComponentModel, baseAddresses); + return WcfServiceExtension.CreateServiceHost(kernel, serviceModel, + model, baseAddresses); } + + return ServiceHostBuilder.Build(handler.ComponentModel, baseAddresses); } protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { return ServiceHostBuilder.Build(serviceType, baseAddresses); } - - private IWcfServiceModel ObtainServiceModel(ComponentModel model) - { - return model.ExtendedProperties[WcfConstants.ServiceModelKey] as IWcfServiceModel; - } } - #region WindsorServiceHostFactory Default + #region WindsorServiceHostFactory Default public class WindsorServiceHostFactory : WindsorServiceHostFactory { -- 2.11.4.GIT