WCF integration update (Added Oran Dennison's approach) [SPRNET-317]

This commit is contained in:
bbaia
2008-08-05 00:22:59 +00:00
parent 3c2e420a70
commit d3d15f0a53
16 changed files with 786 additions and 289 deletions

View File

@@ -1,12 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
@@ -33,12 +28,12 @@
xmlns:aop="http://www.springframework.net/aop">
<!-- Service definition -->
<object id="calculator"
<object id="calculator" singleton="false"
type="Spring.WcfQuickStart.CalculatorService, Spring.WcfQuickStart.ServerApp">
<property name="SleepInSeconds" value="1"/>
</object>
<object type="Spring.ServiceModel.ServiceExporter, Spring.Services">
<object id="calculatorServiceHost" type="Spring.ServiceModel.Activation.ServiceHostFactoryObject, Spring.Services">
<property name="TargetName" value="calculator" />
</object>
@@ -57,20 +52,7 @@
</objects>
</spring>
<common>
<logging>
<!--
You may use http://www.microsoft.com/technet/sysinternals/Miscellaneous/DebugView.mspx
for viewing TraceLogger output
-->
<factoryAdapter type="Common.Logging.Simple.TraceLoggerFactoryAdapter, Common.Logging">
<arg key="Level" value="ALL" />
<!-- Possible values are ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF -->
</factoryAdapter>
</logging>
</common>
<system.serviceModel>
<services>

View File

@@ -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; }

View File

@@ -42,8 +42,8 @@ namespace Spring.WcfQuickStart
Console.Out.WriteLine("--- Press <return> 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();

View File

@@ -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);
}
}

View File

@@ -49,10 +49,6 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Common.Logging, Version=1.0.2.0, Culture=neutral, PublicKeyToken=af08829b84f0328e">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\lib\Net\2.0\Common.Logging.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>

View File

@@ -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";
}
}
}

View File

@@ -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();
}
}

View File

@@ -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" %>

View File

@@ -27,13 +27,13 @@
</context>
<objects xmlns="http://www.springframework.net">
<!-- Service definition -->
<object id="calculator" type="CalculatorService, App_Code"/>
<object id="calculator" type="Spring.WcfQuickStart.CalculatorService, App_Code" singleton="false"/>
</objects>
</spring>
<system.serviceModel>
<services>
<service name="calculator" behaviorConfiguration="DefaultBehavior">
<endpoint address="" binding="basicHttpBinding" contract="ICalculator"/>
<service name="Spring.WcfQuickStart.CalculatorService" behaviorConfiguration="DefaultBehavior">
<endpoint address="" binding="basicHttpBinding" contract="Spring.WcfQuickStart.ICalculator"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>

View File

@@ -1,77 +1,81 @@
#if NET_3_5
#region License
/*
* Copyright <20> 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
{
/// <summary>
/// Factory that provides instances of <see cref="Spring.ServiceModel.ServiceHost" />
/// to host objects created by Spring's IoC container.
/// </summary>
/// <author>Bruno Baia</author>
public class ServiceHostFactory : ServiceHostFactoryBase
{
/// <summary>
/// Creates a <see cref="Spring.ServiceModel.ServiceHost"/> for
/// a specified Spring-managed object with a specific base address.
/// </summary>
/// <param name="reference">
/// A reference to a Spring-managed object 'contextName:objectName'.
/// </param>
/// <param name="baseAddresses">
/// The <see cref="System.Array"/> of type <see cref="System.Uri"/> that contains
/// the base addresses for the service hosted.
/// </param>
/// <returns>
/// A <see cref="Spring.ServiceModel.ServiceHost"/> for the Spring-managed object.
/// </returns>
/// <exception cref="System.ArgumentException">
/// If the Service attribute in the ServiceHost directive was not provided.
/// </exception>
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 <20> 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
{
/// <summary>
/// Factory that provides instances of <see cref="Spring.ServiceModel.SpringServiceHost" />
/// to host objects created by Spring's IoC container.
/// </summary>
/// <author>Bruno Baia</author>
public class ServiceHostFactory : System.ServiceModel.Activation.ServiceHostFactory
{
/// <summary>
/// Creates a <see cref="Spring.ServiceModel.SpringServiceHost"/> for
/// a specified Spring-managed object with a specific base address.
/// </summary>
/// <param name="reference">
/// A reference to a Spring-managed object or to a service type.
/// </param>
/// <param name="baseAddresses">
/// The <see cref="System.Array"/> of type <see cref="System.Uri"/> that contains
/// the base addresses for the service hosted.
/// </param>
/// <returns>
/// A <see cref="Spring.ServiceModel.SpringServiceHost"/> for the Spring-managed object.
/// </returns>
/// <exception cref="System.ArgumentException">
/// If the Service attribute in the ServiceHost directive was not provided.
/// </exception>
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

View File

@@ -0,0 +1,202 @@
#if NET_3_5
#region License
/*
* Copyright <20> 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
{
/// <summary>
/// Factory that provides instances of <see cref="Spring.ServiceModel.ServiceHost" />
/// to host objects created with Spring's IoC container.
/// </summary>
/// <author>Bruno Baia</author>
/// <version>$Id: ServiceHostFactory.cs,v 1.2 2007/05/18 21:04:37 bbaia Exp $</version>
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;
/// <summary>
/// The <see cref="Spring.ServiceModel.SpringServiceHost" /> instance managed by this factory.
/// </summary>
protected SpringServiceHost springServiceHost;
#endregion
#region Properties
/// <summary>
/// Gets or sets the name of the target object that should be exposed as a service.
/// </summary>
/// <value>
/// The name of the target object that should be exposed as a service.
/// </value>
public string TargetName
{
get { return _targetName; }
set { _targetName = value; }
}
/// <summary>
/// Gets or sets the base addresses for the hosted service.
/// </summary>
/// <value>
/// The base addresses for the hosted service.
/// </value>
public Uri[] BaseAddresses
{
get { return _baseAddresses; }
set { _baseAddresses = value; }
}
#endregion
#region Constructor(s) / Destructor
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.ServiceModel.Activation.ServiceHostFactoryObject"/> class.
/// </summary>
public ServiceHostFactoryObject()
{
}
#endregion
#region IApplicationContextAware Members
/// <summary>
/// Gets or sets the <see cref="Spring.Context.IApplicationContext"/> that this
/// object runs in.
/// </summary>
public IApplicationContext ApplicationContext
{
get { return _applicationContext; }
set { _applicationContext = value; }
}
#endregion
#region IFactoryObject Members
/// <summary>
/// Return a <see cref="Spring.ServiceModel.SpringServiceHost" /> instance
/// managed by this factory.
/// </summary>
/// <returns>
/// An instance of <see cref="Spring.ServiceModel.SpringServiceHost" />
/// managed by this factory.
/// </returns>
public virtual object GetObject()
{
return springServiceHost;
}
/// <summary>
/// Return the <see cref="System.Type"/> of object that this
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> creates.
/// </summary>
public virtual Type ObjectType
{
get { return typeof(SpringServiceHost); }
}
/// <summary>
/// Always returns <see langword="false"/>
/// </summary>
public virtual bool IsSingleton
{
get { return false; }
}
#endregion
#region IInitializingObject Members
/// <summary>
/// Publish the object
/// </summary>
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

View File

@@ -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
{
/// <summary>
/// Provides a host for Spring-managed services.
/// </summary>
/// <author>Bruno Baia</author>
public class SpringServiceHost : System.ServiceModel.ServiceHost
{
private bool useSpringServiceBehavior = false;
public IApplicationContext ApplicationContext { get; set; }
#region Constructor(s) / Destructor
/// <summary>
/// Creates a new instance of the <see cref="Spring.ServiceModel.SpringServiceHost"/> class.
/// </summary>
/// <param name="serviceName">The name of the service within Spring's IoC container.</param>
/// <param name="baseAddresses">The base addresses for the hosted service.</param>
public SpringServiceHost(string serviceName, params Uri[] baseAddresses)
: this(serviceName, GetApplicationContext(null), baseAddresses)
{
}
/// <summary>
/// Creates a new instance of the <see cref="Spring.ServiceModel.SpringServiceHost"/> class.
/// </summary>
/// <param name="serviceName">The name of the service within Spring's IoC container.</param>
/// <param name="contextName">The name of the Spring context to use.</param>
/// <param name="baseAddresses">The base addresses for the hosted service.</param>
public SpringServiceHost(string serviceName, string contextName, params Uri[] baseAddresses)
: this(serviceName, GetApplicationContext(contextName), baseAddresses)
{
}
/// <summary>
/// Creates a new instance of the <see cref="Spring.ServiceModel.SpringServiceHost"/> class.
/// </summary>
/// <param name="serviceName">The name of the service within Spring's IoC container.</param>
/// <param name="applicationContext">The <see cref="IApplicationContext"/> to use.</param>
/// <param name="baseAddresses">The base addresses for the hosted service.</param>
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<SpringServiceBehavior>() == null)
{
this.Description.Behaviors.Add(new SpringServiceBehavior(ApplicationContext));
}
base.OnOpening();
}
}
}
#endif

View File

@@ -1,136 +1,140 @@
#if NET_3_5
#region License
/*
* Copyright <20> 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
{
/// <summary>
/// Builds a WCF service type.
/// </summary>
/// <author>Bruno Baia</author>
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
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.ServiceModel.Support.ServiceProxyTypeBuilder"/> class.
/// </summary>
/// <param name="contextName">The name of the context to use.</param>
/// <param name="serviceName">The name of the service within Spring's IoC container.</param>
/// <param name="serviceType">The type of the service.</param>
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
/// <summary>
/// Implements constructors for the proxy class.
/// </summary>
/// <remarks>
/// This implementation generates a constructor
/// that gets instance of the target object using
/// <see cref="Spring.Objects.Factory.IObjectFactory.GetObject(string)"/>.
/// </remarks>
/// <param name="builder">
/// The <see cref="System.Type"/> builder to use.
/// </param>
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);
}
/// <summary>
/// Creates an appropriate type builder.
/// </summary>
/// <param name="name">The name to use for the proxy type name.</param>
/// <param name="baseType">The type to extends if provided.</param>
/// <returns>The type builder to use.</returns>
protected override TypeBuilder CreateTypeBuilder(string name, Type baseType)
{
return DynamicProxyManager.CreateTypeBuilder(name, baseType);
}
#endregion
}
}
#if NET_3_5
#region License
/*
* Copyright <20> 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
{
/// <summary>
/// Builds a WCF service type.
/// </summary>
/// <author>Bruno Baia</author>
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;
/// <summary>
/// Target instance calls should be delegated to.
/// </summary>
protected FieldBuilder applicationContextField;
#endregion
#region Constructor(s) / Destructor
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.ServiceModel.Support.ServiceProxyTypeBuilder"/> class.
/// </summary>
/// <param name="serviceName">The name of the service within Spring's IoC container.</param>
/// <param name="applicationContext">The <see cref="IApplicationContext"/> to use.</param>
/// <param name="serviceType">The type of the service.</param>
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;
}
/// <summary>
/// Implements constructors for the proxy class.
/// </summary>
/// <remarks>
/// This implementation generates a constructor
/// that gets instance of the target object using
/// <see cref="Spring.Objects.Factory.IObjectFactory.GetObject(string)"/>.
/// </remarks>
/// <param name="builder">
/// The <see cref="System.Type"/> builder to use.
/// </param>
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);
}
/// <summary>
/// Creates an appropriate type builder.
/// </summary>
/// <param name="name">The name to use for the proxy type name.</param>
/// <param name="baseType">The type to extends if provided.</param>
/// <returns>The type builder to use.</returns>
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

View File

@@ -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

View File

@@ -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<ServiceEndpoint> 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

View File

@@ -126,13 +126,13 @@
<Compile Include="Remoting\SaoFactoryObject.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ServiceModel\Activation\ServiceHostFactory.cs" />
<Compile Include="ServiceModel\ServiceExporter.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ServiceModel\ServiceHost.cs">
<Compile Include="ServiceModel\Activation\ServiceHostFactory.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ServiceModel\Activation\ServiceHostFactoryObject.cs" />
<Compile Include="ServiceModel\Support\SpringInstanceProvider.cs" />
<Compile Include="ServiceModel\Support\SpringServiceBehavior.cs" />
<Compile Include="ServiceModel\SpringServiceHost.cs" />
<Compile Include="ServiceModel\Support\ServiceProxyTypeBuilder.cs" />
<Compile Include="Web\Services\WebServiceProxyFactory.cs">
<SubType>Code</SubType>