From d3d15f0a53ae3a98c2c5f0506344cc6e345cdbf0 Mon Sep 17 00:00:00 2001 From: bbaia Date: Tue, 5 Aug 2008 00:22:59 +0000 Subject: [PATCH] WCF integration update (Added Oran Dennison's approach) [SPRNET-317] --- .../Spring.WcfQuickStart.ServerApp/App.config | 24 +- .../CalculatorService.cs | 3 +- .../Spring.WcfQuickStart.ServerApp/Program.cs | 4 +- .../SimplePerformanceInterceptor.cs | 12 +- ...Spring.WcfQuickStart.ServerApp.2008.csproj | 4 - .../App_Code/CalculatorService.cs | 41 +-- .../App_Code/ICalculator.cs | 27 +- .../Calculator.svc | 2 +- .../Spring.WcfQuickStart.Web.2008/Web.config | 6 +- .../Activation/ServiceHostFactory.cs | 156 +++++----- .../Activation/ServiceHostFactoryObject.cs | 202 +++++++++++++ .../ServiceModel/SpringServiceHost.cs | 130 +++++++++ .../Support/ServiceProxyTypeBuilder.cs | 274 +++++++++--------- .../Support/SpringInstanceProvider.cs | 85 ++++++ .../Support/SpringServiceBehavior.cs | 95 ++++++ .../Spring.Services.2008.csproj | 10 +- 16 files changed, 786 insertions(+), 289 deletions(-) create mode 100644 src/Spring/Spring.Services/ServiceModel/Activation/ServiceHostFactoryObject.cs create mode 100644 src/Spring/Spring.Services/ServiceModel/SpringServiceHost.cs create mode 100644 src/Spring/Spring.Services/ServiceModel/Support/SpringInstanceProvider.cs create mode 100644 src/Spring/Spring.Services/ServiceModel/Support/SpringServiceBehavior.cs diff --git a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/App.config b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/App.config index 212cb362..cf613534 100644 --- a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/App.config +++ b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/App.config @@ -1,12 +1,7 @@ - - - -
-
@@ -33,12 +28,12 @@ xmlns:aop="http://www.springframework.net/aop"> - - + @@ -57,20 +52,7 @@ - - - - - - - - - - - + diff --git a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/CalculatorService.cs b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/CalculatorService.cs index a4ab946b..4c75d05a 100644 --- a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/CalculatorService.cs +++ b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/CalculatorService.cs @@ -1,13 +1,14 @@ using System; using System.Threading; +//using System.ServiceModel; namespace Spring.WcfQuickStart { + //[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class CalculatorService : ICalculator { private int sleepInSeconds; - public int SleepInSeconds { get { return sleepInSeconds; } diff --git a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/Program.cs b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/Program.cs index 9a828c24..6d4d8df0 100644 --- a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/Program.cs +++ b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/Program.cs @@ -42,8 +42,8 @@ namespace Spring.WcfQuickStart Console.Out.WriteLine("--- Press to quit ---"); Console.ReadLine(); - // Programmatically (You need to comment 'ServiceExporter' object definition in App.config) - //using (ServiceHost serviceHost = new ServiceHost("calculator")) + // Programmatically (You need to comment 'calculatorServiceHost' object definition in App.config) + //using (SpringServiceHost serviceHost = new SpringServiceHost("calculator")) //{ // serviceHost.Open(); diff --git a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/SimplePerformanceInterceptor.cs b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/SimplePerformanceInterceptor.cs index 09415498..4ff597e0 100644 --- a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/SimplePerformanceInterceptor.cs +++ b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/SimplePerformanceInterceptor.cs @@ -1,21 +1,14 @@ using System; using System.Reflection; + using AopAlliance.Intercept; -using Common.Logging; namespace Spring.WcfQuickStart { public class SimplePerformanceInterceptor : IMethodInterceptor { - #region Logging Definition - - private readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - #endregion - private string prefix = "Invocation took"; - public string Prefix { get { return prefix; } @@ -34,9 +27,8 @@ namespace Spring.WcfQuickStart finally { DateTime stop = DateTime.Now; - TimeSpan time = stop - start; - log.Info(Prefix + " " + time); + Console.Out.WriteLine(Prefix + " " + time); } } diff --git a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/Spring.WcfQuickStart.ServerApp.2008.csproj b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/Spring.WcfQuickStart.ServerApp.2008.csproj index edbd6b42..9a0969e6 100644 --- a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/Spring.WcfQuickStart.ServerApp.2008.csproj +++ b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.ServerApp/Spring.WcfQuickStart.ServerApp.2008.csproj @@ -49,10 +49,6 @@ 4 - - False - ..\..\..\..\..\lib\Net\2.0\Common.Logging.dll - 3.5 diff --git a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/App_Code/CalculatorService.cs b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/App_Code/CalculatorService.cs index 49a8051b..efdadb49 100644 --- a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/App_Code/CalculatorService.cs +++ b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/App_Code/CalculatorService.cs @@ -1,29 +1,32 @@ using System; -public class CalculatorService : ICalculator +namespace Spring.WcfQuickStart { - public double Add(double n1, double n2) + public class CalculatorService : ICalculator { - return n1 + n2; - } + public double Add(double n1, double n2) + { + return n1 + n2; + } - public double Subtract(double n1, double n2) - { - return n1 - n2; - } + public double Subtract(double n1, double n2) + { + return n1 - n2; + } - public double Multiply(double n1, double n2) - { - return n1 * n2; - } + public double Multiply(double n1, double n2) + { + return n1 * n2; + } - public double Divide(double n1, double n2) - { - return n1 / n2; - } + public double Divide(double n1, double n2) + { + return n1 / n2; + } - public string GetName() - { - return "Web Calculator"; + public string GetName() + { + return "Web Calculator"; + } } } \ No newline at end of file diff --git a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/App_Code/ICalculator.cs b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/App_Code/ICalculator.cs index 7e789a9f..f2909aa0 100644 --- a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/App_Code/ICalculator.cs +++ b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/App_Code/ICalculator.cs @@ -1,17 +1,20 @@ using System; using System.ServiceModel; -[ServiceContract(Namespace = "http://Spring.WcfQuickStart")] -public interface ICalculator +namespace Spring.WcfQuickStart { - [OperationContract] - double Add(double n1, double n2); - [OperationContract] - double Subtract(double n1, double n2); - [OperationContract] - double Multiply(double n1, double n2); - [OperationContract] - double Divide(double n1, double n2); - [OperationContract] - string GetName(); + [ServiceContract(Namespace = "http://Spring.WcfQuickStart")] + public interface ICalculator + { + [OperationContract] + double Add(double n1, double n2); + [OperationContract] + double Subtract(double n1, double n2); + [OperationContract] + double Multiply(double n1, double n2); + [OperationContract] + double Divide(double n1, double n2); + [OperationContract] + string GetName(); + } } diff --git a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/Calculator.svc b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/Calculator.svc index 648abc09..4e74bec9 100644 --- a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/Calculator.svc +++ b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/Calculator.svc @@ -1 +1 @@ -<%@ ServiceHost Language="C#" Debug="true" Service="calculator" Factory="Spring.ServiceModel.Activation.ServiceHostFactory" %> +<%@ ServiceHost Language="C#" Debug="true" Service="Spring.WcfQuickStart.CalculatorService" Factory="Spring.ServiceModel.Activation.ServiceHostFactory" %> diff --git a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/Web.config b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/Web.config index 2ea602fe..43b986fe 100644 --- a/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/Web.config +++ b/examples/Spring/Spring.WcfQuickStart/src/Spring.WcfQuickStart.Web.2008/Web.config @@ -27,13 +27,13 @@ - + - - + + diff --git a/src/Spring/Spring.Services/ServiceModel/Activation/ServiceHostFactory.cs b/src/Spring/Spring.Services/ServiceModel/Activation/ServiceHostFactory.cs index d530459f..b67fd97a 100644 --- a/src/Spring/Spring.Services/ServiceModel/Activation/ServiceHostFactory.cs +++ b/src/Spring/Spring.Services/ServiceModel/Activation/ServiceHostFactory.cs @@ -1,77 +1,81 @@ -#if NET_3_5 -#region License - -/* - * Copyright © 2002-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#endregion - -#region Imports - -using System; -using System.ServiceModel; -using System.ServiceModel.Activation; - -using Spring.Util; - -#endregion - -namespace Spring.ServiceModel.Activation -{ - /// - /// Factory that provides instances of - /// to host objects created by Spring's IoC container. - /// - /// Bruno Baia - public class ServiceHostFactory : ServiceHostFactoryBase - { - /// - /// Creates a for - /// a specified Spring-managed object with a specific base address. - /// - /// - /// A reference to a Spring-managed object 'contextName:objectName'. - /// - /// - /// The of type that contains - /// the base addresses for the service hosted. - /// - /// - /// A for the Spring-managed object. - /// - /// - /// If the Service attribute in the ServiceHost directive was not provided. - /// - public override ServiceHostBase CreateServiceHost(string reference, Uri[] baseAddresses) - { - if (StringUtils.IsNullOrEmpty(reference)) - { - throw new ArgumentException("The service name was not provided in the ServiceHost directive.", "Service"); - } - - string[] refSplitted = reference.Split(':'); - if (refSplitted.Length == 2) - { - return new ServiceHost(refSplitted[0], refSplitted[1], baseAddresses); - } - else - { - return new ServiceHost(reference, baseAddresses); - } - } - } -} +#if NET_3_5 +#region License + +/* + * Copyright © 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; +using System.ServiceModel; + +using Spring.Util; +using Spring.Context.Support; +using Spring.Context; + +#endregion + +namespace Spring.ServiceModel.Activation +{ + /// + /// Factory that provides instances of + /// to host objects created by Spring's IoC container. + /// + /// Bruno Baia + public class ServiceHostFactory : System.ServiceModel.Activation.ServiceHostFactory + { + /// + /// Creates a for + /// a specified Spring-managed object with a specific base address. + /// + /// + /// A reference to a Spring-managed object or to a service type. + /// + /// + /// The of type that contains + /// the base addresses for the service hosted. + /// + /// + /// A for the Spring-managed object. + /// + /// + /// If the Service attribute in the ServiceHost directive was not provided. + /// + public override ServiceHostBase CreateServiceHost(string reference, Uri[] baseAddresses) + { + if (StringUtils.IsNullOrEmpty(reference)) + { + return base.CreateServiceHost(reference, baseAddresses); + } + + IApplicationContext applicationContext = ContextRegistry.GetContext(); + if (applicationContext.ContainsObject(reference)) + { + return new SpringServiceHost(reference, applicationContext, baseAddresses); + } + + return base.CreateServiceHost(reference, baseAddresses); + } + + protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) + { + return new SpringServiceHost(serviceType, baseAddresses); + } + } +} #endif \ No newline at end of file diff --git a/src/Spring/Spring.Services/ServiceModel/Activation/ServiceHostFactoryObject.cs b/src/Spring/Spring.Services/ServiceModel/Activation/ServiceHostFactoryObject.cs new file mode 100644 index 00000000..1388edbb --- /dev/null +++ b/src/Spring/Spring.Services/ServiceModel/Activation/ServiceHostFactoryObject.cs @@ -0,0 +1,202 @@ +#if NET_3_5 +#region License + +/* + * Copyright © 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; +using System.ServiceModel; +using System.ServiceModel.Activation; + +using Spring.Util; +using Spring.Context; +using Spring.Objects.Factory; +using Spring.Objects.Factory.Config; + +#endregion + +namespace Spring.ServiceModel.Activation +{ + /// + /// Factory that provides instances of + /// to host objects created with Spring's IoC container. + /// + /// Bruno Baia + /// $Id: ServiceHostFactory.cs,v 1.2 2007/05/18 21:04:37 bbaia Exp $ + public class ServiceHostFactoryObject : IFactoryObject, IApplicationContextAware, IInitializingObject, IDisposable + { + #region Logging + + private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof(ServiceHostFactoryObject)); + + #endregion + + #region Fields + + private string _targetName; + private Uri[] _baseAddresses = new Uri[] { }; + private IApplicationContext _applicationContext; + + /// + /// The instance managed by this factory. + /// + protected SpringServiceHost springServiceHost; + + #endregion + + #region Properties + + /// + /// Gets or sets the name of the target object that should be exposed as a service. + /// + /// + /// The name of the target object that should be exposed as a service. + /// + public string TargetName + { + get { return _targetName; } + set { _targetName = value; } + } + + /// + /// Gets or sets the base addresses for the hosted service. + /// + /// + /// The base addresses for the hosted service. + /// + public Uri[] BaseAddresses + { + get { return _baseAddresses; } + set { _baseAddresses = value; } + } + + #endregion + + #region Constructor(s) / Destructor + + /// + /// Creates a new instance of the + /// class. + /// + public ServiceHostFactoryObject() + { + } + + #endregion + + #region IApplicationContextAware Members + + /// + /// Gets or sets the that this + /// object runs in. + /// + public IApplicationContext ApplicationContext + { + get { return _applicationContext; } + set { _applicationContext = value; } + } + + #endregion + + #region IFactoryObject Members + + /// + /// Return a instance + /// managed by this factory. + /// + /// + /// An instance of + /// managed by this factory. + /// + public virtual object GetObject() + { + return springServiceHost; + } + + /// + /// Return the of object that this + /// creates. + /// + public virtual Type ObjectType + { + get { return typeof(SpringServiceHost); } + } + + /// + /// Always returns + /// + public virtual bool IsSingleton + { + get { return false; } + } + + #endregion + + #region IInitializingObject Members + + /// + /// Publish the object + /// + public void AfterPropertiesSet() + { + ValidateConfiguration(); + + springServiceHost = new SpringServiceHost(TargetName, _applicationContext, BaseAddresses); + + springServiceHost.Open(); + + #region Instrumentation + + if (LOG.IsInfoEnabled) + { + LOG.Info(String.Format("The service '{0}' is ready and can now be accessed.", TargetName)); + } + + #endregion + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + if (springServiceHost != null) + { + springServiceHost.Close(); + } + } + + #endregion + + #region Private Methods + + private void ValidateConfiguration() + { + if (TargetName == null) + { + throw new ArgumentException("The TargetName property is required."); + } + } + + #endregion + } +} +#endif \ No newline at end of file diff --git a/src/Spring/Spring.Services/ServiceModel/SpringServiceHost.cs b/src/Spring/Spring.Services/ServiceModel/SpringServiceHost.cs new file mode 100644 index 00000000..856685cd --- /dev/null +++ b/src/Spring/Spring.Services/ServiceModel/SpringServiceHost.cs @@ -0,0 +1,130 @@ +#if NET_3_5 +#region License + +/* + * Copyright © 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; + +using Spring.Util; +using Spring.Context; +using Spring.Context.Support; +using Spring.ServiceModel.Support; +using Spring.ServiceModel.Dispatcher; + +#endregion + +namespace Spring.ServiceModel +{ + /// + /// Provides a host for Spring-managed services. + /// + /// Bruno Baia + public class SpringServiceHost : System.ServiceModel.ServiceHost + { + private bool useSpringServiceBehavior = false; + + public IApplicationContext ApplicationContext { get; set; } + + #region Constructor(s) / Destructor + + /// + /// Creates a new instance of the class. + /// + /// The name of the service within Spring's IoC container. + /// The base addresses for the hosted service. + public SpringServiceHost(string serviceName, params Uri[] baseAddresses) + : this(serviceName, GetApplicationContext(null), baseAddresses) + { + } + + /// + /// Creates a new instance of the class. + /// + /// The name of the service within Spring's IoC container. + /// The name of the Spring context to use. + /// The base addresses for the hosted service. + public SpringServiceHost(string serviceName, string contextName, params Uri[] baseAddresses) + : this(serviceName, GetApplicationContext(contextName), baseAddresses) + { + } + + /// + /// Creates a new instance of the class. + /// + /// The name of the service within Spring's IoC container. + /// The to use. + /// The base addresses for the hosted service. + public SpringServiceHost(string serviceName, IApplicationContext applicationContext, params Uri[] baseAddresses) + : base(CreateServiceType(serviceName, applicationContext), baseAddresses) + { + ApplicationContext = applicationContext; + } + + public SpringServiceHost(Type serviceType, params Uri[] baseAddresses) + : this(serviceType, GetApplicationContext(null), baseAddresses) + { + } + + public SpringServiceHost(Type serviceType, IApplicationContext applicationContext, params Uri[] baseAddresses) + : base(serviceType, baseAddresses) + { + useSpringServiceBehavior = true; + ApplicationContext = applicationContext; + } + + private static IApplicationContext GetApplicationContext(string contextName) + { + if (StringUtils.IsNullOrEmpty(contextName)) + { + return ContextRegistry.GetContext(); + } + else + { + return ContextRegistry.GetContext(contextName); + } + } + + private static Type CreateServiceType(string serviceName, IApplicationContext applicationContext) + { + if (StringUtils.IsNullOrEmpty(serviceName)) + { + throw new ArgumentException("The service name cannot be null or an empty string.", "serviceName"); + } + + Type serviceType = applicationContext.GetType(serviceName); + + return new ServiceProxyTypeBuilder(serviceName, applicationContext, serviceType).BuildProxyType(); + } + + #endregion + + protected override void OnOpening() + { + if (this.useSpringServiceBehavior && + this.Description.Behaviors.Find() == null) + { + this.Description.Behaviors.Add(new SpringServiceBehavior(ApplicationContext)); + } + base.OnOpening(); + } + } +} +#endif \ No newline at end of file diff --git a/src/Spring/Spring.Services/ServiceModel/Support/ServiceProxyTypeBuilder.cs b/src/Spring/Spring.Services/ServiceModel/Support/ServiceProxyTypeBuilder.cs index e14e6365..5ee2938f 100644 --- a/src/Spring/Spring.Services/ServiceModel/Support/ServiceProxyTypeBuilder.cs +++ b/src/Spring/Spring.Services/ServiceModel/Support/ServiceProxyTypeBuilder.cs @@ -1,136 +1,140 @@ -#if NET_3_5 -#region License - -/* - * Copyright © 2002-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#endregion - -#region Imports - -using System; -using System.Reflection; -using System.Reflection.Emit; - -using Spring.Proxy; -using Spring.Context; -using Spring.Context.Support; -using Spring.Objects.Factory; - -#endregion - -namespace Spring.ServiceModel.Support -{ - /// - /// Builds a WCF service type. - /// - /// Bruno Baia - public class ServiceProxyTypeBuilder : CompositionProxyTypeBuilder - { - #region Fields - - private static readonly MethodInfo GetObject = - typeof(IObjectFactory).GetMethod("GetObject", new Type[] { typeof(string) }); - - private static readonly MethodInfo GetContext = - typeof(ContextRegistry).GetMethod("GetContext", Type.EmptyTypes); - - private static readonly MethodInfo GetContextByName = - typeof(ContextRegistry).GetMethod("GetContext", new Type[] { typeof(string) }); - - private string contextName; - private string serviceName; - - #endregion - - #region Constructor(s) / Destructor - - /// - /// Creates a new instance of the - /// class. - /// - /// The name of the context to use. - /// The name of the service within Spring's IoC container. - /// The type of the service. - public ServiceProxyTypeBuilder(string contextName, string serviceName, Type serviceType) - { - this.contextName = contextName; - this.serviceName = serviceName; - - this.Name = (contextName == null) ? serviceName : contextName + "." + serviceName; - this.TargetType = serviceType; - } - - #endregion - - #region Protected Methods - - /// - /// Implements constructors for the proxy class. - /// - /// - /// This implementation generates a constructor - /// that gets instance of the target object using - /// . - /// - /// - /// The builder to use. - /// - protected override void ImplementConstructors(TypeBuilder builder) - { - MethodAttributes attributes = MethodAttributes.Public | - MethodAttributes.HideBySig | MethodAttributes.SpecialName | - MethodAttributes.RTSpecialName; - - ConstructorBuilder cb = builder.DefineConstructor( - attributes, CallingConventions.Standard, Type.EmptyTypes); - - ILGenerator il = cb.GetILGenerator(); - - il.Emit(OpCodes.Ldarg_0); - if (contextName == null) - { - // call ContextRegistry.GetContext() - il.EmitCall(OpCodes.Call, GetContext, null); - } - else - { - // call ContextRegistry.GetContext(contextName) - il.Emit(OpCodes.Ldstr, contextName); - il.EmitCall(OpCodes.Call, GetContextByName, null); - } - il.Emit(OpCodes.Ldstr, serviceName); - il.EmitCall(OpCodes.Callvirt, GetObject, null); - il.Emit(OpCodes.Stfld, targetInstance); - - il.Emit(OpCodes.Ret); - } - - /// - /// Creates an appropriate type builder. - /// - /// The name to use for the proxy type name. - /// The type to extends if provided. - /// The type builder to use. - protected override TypeBuilder CreateTypeBuilder(string name, Type baseType) - { - return DynamicProxyManager.CreateTypeBuilder(name, baseType); - } - - #endregion - } -} +#if NET_3_5 +#region License + +/* + * Copyright © 2002-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; +using System.Reflection; +using System.Reflection.Emit; + +using Spring.Proxy; +using Spring.Context; +using Spring.Context.Support; +using Spring.Objects.Factory; + +#endregion + +namespace Spring.ServiceModel.Support +{ + /// + /// Builds a WCF service type. + /// + /// Bruno Baia + public class ServiceProxyTypeBuilder : CompositionProxyTypeBuilder + { + #region Fields + + private static readonly MethodInfo GetObject = + typeof(IObjectFactory).GetMethod("GetObject", new Type[] { typeof(string) }); + + private IApplicationContext applicationContext; + private string serviceName; + + /// + /// Target instance calls should be delegated to. + /// + protected FieldBuilder applicationContextField; + + #endregion + + #region Constructor(s) / Destructor + + /// + /// Creates a new instance of the + /// class. + /// + /// The name of the service within Spring's IoC container. + /// The to use. + /// The type of the service. + public ServiceProxyTypeBuilder(string serviceName, IApplicationContext applicationContext, Type serviceType) + { + this.serviceName = serviceName; + this.applicationContext = applicationContext; + + this.Name = serviceName; + this.TargetType = serviceType; + } + + #endregion + + #region Protected Methods + + public override Type BuildProxyType() + { + Type proxyType = base.BuildProxyType(); + + FieldInfo field = proxyType.GetField("__applicationContext", BindingFlags.NonPublic | BindingFlags.Static); + field.SetValue(proxyType, applicationContext); + + return proxyType; + } + + /// + /// Implements constructors for the proxy class. + /// + /// + /// This implementation generates a constructor + /// that gets instance of the target object using + /// . + /// + /// + /// The builder to use. + /// + protected override void ImplementConstructors(TypeBuilder builder) + { + MethodAttributes attributes = MethodAttributes.Public | + MethodAttributes.HideBySig | MethodAttributes.SpecialName | + MethodAttributes.RTSpecialName; + + ConstructorBuilder cb = builder.DefineConstructor( + attributes, CallingConventions.Standard, Type.EmptyTypes); + + ILGenerator il = cb.GetILGenerator(); + + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldsfld, applicationContextField); + il.Emit(OpCodes.Ldstr, serviceName); + il.EmitCall(OpCodes.Callvirt, GetObject, null); + il.Emit(OpCodes.Stfld, targetInstance); + + il.Emit(OpCodes.Ret); + } + + /// + /// Creates an appropriate type builder. + /// + /// The name to use for the proxy type name. + /// The type to extends if provided. + /// The type builder to use. + protected override TypeBuilder CreateTypeBuilder(string name, Type baseType) + { + TypeBuilder typeBuilder = DynamicProxyManager.CreateTypeBuilder(name, baseType); + + applicationContextField = typeBuilder.DefineField("__applicationContext", typeof(IApplicationContext), + FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.InitOnly); + + return typeBuilder; + } + + #endregion + } +} #endif \ No newline at end of file diff --git a/src/Spring/Spring.Services/ServiceModel/Support/SpringInstanceProvider.cs b/src/Spring/Spring.Services/ServiceModel/Support/SpringInstanceProvider.cs new file mode 100644 index 00000000..1e62c167 --- /dev/null +++ b/src/Spring/Spring.Services/ServiceModel/Support/SpringInstanceProvider.cs @@ -0,0 +1,85 @@ +#if NET_3_5 +#region License + +/* + * Copyright © 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; +using System.ServiceModel; +using System.ServiceModel.Dispatcher; +using System.ServiceModel.Channels; + +using Spring.Context; +using System.Globalization; + +#endregion + +namespace Spring.ServiceModel.Dispatcher +{ + public class SpringInstanceProvider : IInstanceProvider + { + public IApplicationContext ApplicationContext { get; set; } + + public Type ServiceType { get; set; } + + public SpringInstanceProvider(IApplicationContext applicationContext) + { + ApplicationContext = applicationContext; + } + + public SpringInstanceProvider(IApplicationContext applicationContext, Type type) + { + ApplicationContext = applicationContext; + ServiceType = type; + } + + #region IInstanceProvider Members + + public object GetInstance(InstanceContext instanceContext) + { + return GetInstance(instanceContext, null); + } + + public object GetInstance(InstanceContext instanceContext, Message message) + { + object result = null; + + string[] objectNames = ApplicationContext.GetObjectNamesForType(ServiceType); + if (objectNames.Length != 1) + { + // TODO : Exception type and message ? + throw new InvalidOperationException( + string.Format( + CultureInfo.InvariantCulture, + "There must exist exactly one object definition of type '{0}' in the Spring container.", + ServiceType.FullName) + ); + } + return ApplicationContext.GetObject(objectNames[0]); + } + + public void ReleaseInstance(InstanceContext instanceContext, object instance) + { + } + + #endregion + } +} +#endif \ No newline at end of file diff --git a/src/Spring/Spring.Services/ServiceModel/Support/SpringServiceBehavior.cs b/src/Spring/Spring.Services/ServiceModel/Support/SpringServiceBehavior.cs new file mode 100644 index 00000000..121188fc --- /dev/null +++ b/src/Spring/Spring.Services/ServiceModel/Support/SpringServiceBehavior.cs @@ -0,0 +1,95 @@ +#if NET_3_5 +#region License + +/* + * Copyright © 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; +using System.Collections.ObjectModel; +using System.ServiceModel; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; +using System.ServiceModel.Dispatcher; + +using Spring.Context; +using Spring.Context.Support; +using Spring.Util; + +#endregion + +namespace Spring.ServiceModel.Dispatcher +{ + public class SpringServiceBehavior : IServiceBehavior + { + public SpringInstanceProvider InstanceProvider { get; set; } + + public string ContextName { get; set; } + + public SpringServiceBehavior() + { + IApplicationContext applicationContext; + if (StringUtils.IsNullOrEmpty(ContextName)) + { + applicationContext = ContextRegistry.GetContext(); + } + else + { + applicationContext = ContextRegistry.GetContext(ContextName); + } + + InstanceProvider = new SpringInstanceProvider(applicationContext); + } + + public SpringServiceBehavior(IApplicationContext applicationContext) + { + InstanceProvider = new SpringInstanceProvider(applicationContext); + } + + #region IServiceBehavior Members + + public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, + Collection endpoints, BindingParameterCollection bindingParameters) + { + } + + public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) + { + foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers) + { + ChannelDispatcher cd = cdb as ChannelDispatcher; + if (cd != null) + { + foreach (EndpointDispatcher ed in cd.Endpoints) + { + InstanceProvider.ServiceType = serviceDescription.ServiceType; + ed.DispatchRuntime.InstanceProvider = InstanceProvider; + } + } + } + } + + public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) + { + } + + #endregion + } +} +#endif \ No newline at end of file diff --git a/src/Spring/Spring.Services/Spring.Services.2008.csproj b/src/Spring/Spring.Services/Spring.Services.2008.csproj index 04183d18..e4e9c2fd 100644 --- a/src/Spring/Spring.Services/Spring.Services.2008.csproj +++ b/src/Spring/Spring.Services/Spring.Services.2008.csproj @@ -126,13 +126,13 @@ Code - - - Code - - + Code + + + + Code