fixed SPRNET-1379, Calculator EnterpriseService example

This commit is contained in:
eeichinger
2010-10-31 02:51:35 +00:00
parent 9e6b5a0f70
commit a997f32044
9 changed files with 162 additions and 71 deletions

View File

@@ -34,7 +34,7 @@
<!-- ================================== -->
<!-- In process (local) implementations -->
<!-- ================================== -->
<resource uri="assembly://Spring.Calculator.ClientApp/Spring.Calculator.ClientApp.Config.InProcess/inProcess.xml" />
<!-- resource uri="assembly://Spring.Calculator.ClientApp/Spring.Calculator.ClientApp.Config.InProcess/inProcess.xml" / -->
<!-- ======================== -->
<!-- Remoting implementations -->
@@ -64,7 +64,7 @@
<!-- EnterpriseService implementations -->
<!-- ================================= -->
<!-- Make sure you register components with 'RegisterComponentServices' console application. -->
<!-- resource uri="assembly://Spring.Calculator.ClientApp/Spring.Calculator.ClientApp.Config.EnterpriseServices/enterpriseServices.xml" />-->
<resource uri="assembly://Spring.Calculator.ClientApp/Spring.Calculator.ClientApp.Config.EnterpriseServices/enterpriseServices.xml" />
</context>

View File

@@ -56,17 +56,19 @@
<!-- Export components into assembly and autoregister with COM+ -->
<object type="Spring.EnterpriseServices.EnterpriseServicesExporter, Spring.Services">
<!-- assembly name to generated - will generate 'Spring.Calculator.EnterpriseServices.dll' -->
<!-- assembly name to generate - will generate 'Spring.Calculator.EnterpriseServices.dll' -->
<property name="Assembly" value="Spring.Calculator.EnterpriseServices" />
<!--
use Spring's ContextRegistry for managing services. If true, requires a file
'Spring.Calculator.EnterpriseServices.dll.spring-context.xml' containing a
<spring/context /> section placed next to the generated assembly.
'Spring.Calculator.EnterpriseServices.dll.config' (for 'Library')
'Spring.Calculator.EnterpriseServices.exe.config' (for 'Server')
containing a <spring/context /> section placed next to the generated assembly.
-->
<property name="UseSpring" value="true" />
<property name="ApplicationName" value="Spring Calculator Application" />
<property name="ActivationMode" value="Library" />
<!--<property name="ActivationMode" value="Library" />-->
<property name="ActivationMode" value="Server" />
<property name="Description" value="Spring Calculator application" />
<property name="Components">
<list>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
</sectionGroup>
</configSections>
<!--
Note that in-proc components must use a unique context name
to prevent clashes with the app's root context!
-->
<spring>
<context name="calculatorComponent">
<resource uri="Config/services.xml" />
</context>
</spring>
</configuration>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<spring>
<context>
<resource uri="Config/services.xml" />
</context>
</spring>

View File

@@ -0,0 +1,25 @@
<?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" />
</sectionGroup>
</configSections>
<common>
<logging>
<factoryAdapter type="Common.Logging.Simple.TraceLoggerFactoryAdapter, Common.Logging">
<arg key="level" value="ALL" />
</factoryAdapter>
</logging>
</common>
<spring>
<context>
<resource uri="Config/services.xml" />
</context>
</spring>
</configuration>

View File

@@ -77,6 +77,13 @@
</PropertyGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="Spring.Calculator.EnterpriseServices.dll.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Spring.Calculator.EnterpriseServices.exe.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Spring.Calculator.RegisterComponentServices.build" />
<Compile Include="AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
@@ -112,9 +119,6 @@
<Content Include="Config\services.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Spring.Calculator.EnterpriseServices.dll.spring-context.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>

View File

@@ -22,6 +22,7 @@
#region Imports
using System;
using System.EnterpriseServices;
using Spring.Context.Support;
@@ -30,12 +31,25 @@ using Spring.Context.Support;
namespace Spring.EnterpriseServices
{
/// <summary>
/// Handles loading of &lt;spring/context&gt; configuration sections for <see cref="ServicedComponent"/>s
/// generated by <see cref="EnterpriseServicesExporter"/>.
/// Handles loading of &lt;spring/context&gt; configuration sections for
/// in-process <see cref="ServicedComponent"/>s generated by
/// <see cref="EnterpriseServicesExporter"/>.
/// </summary>
/// <author>Erich Eichinger</author>
[Obsolete("not used anymore")]
public class ServicedComponentContextHandler : ContextHandler
{}
{
/// <summary>
/// Prevent auto-registering the context with the global ContextRegistry
/// </summary>
protected override bool AutoRegisterWithContextRegistry
{
get
{
return false;
}
}
}
}
#endif

View File

@@ -22,8 +22,9 @@
#region Imports
using System;
using System;
using System.Diagnostics;
using System.Reflection;
using Spring.Util;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Support;
@@ -151,7 +152,8 @@ namespace Spring.EnterpriseServices
public void AfterPropertiesSet()
{
ValidateConfiguration();
componentType = Type.GetTypeFromProgID(Name, Server);
componentType = Type.GetTypeFromProgID(Name, Server);
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
#endregion
@@ -172,9 +174,14 @@ namespace Spring.EnterpriseServices
/// <returns>New instance of serviced component.</returns>
private object CreateInstance()
{
return Activator.CreateInstance(componentType);
}
return Activator.CreateInstance(componentType);
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
return Assembly.LoadFrom(componentType.Assembly.CodeBase);
}
#endregion
}
}

View File

@@ -68,59 +68,80 @@ namespace Spring.EnterpriseServices
{
if (isInitialized) return;
isInitialized = true;
// this is to ensure, that assemblies placed next to the component assembly can be loaded
// even when they are not strong named.
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
FileInfo componentAssemblyFile = new FileInfo(componentType.Assembly.Location);
componentDirectory = componentAssemblyFile.Directory.FullName;
// switch to component assembly's directory (affects resolving relative paths during context instantiation!)
Environment.CurrentDirectory = componentDirectory;
// read in config file if any
FileInfo configFile = new FileInfo(componentAssemblyFile.FullName);
if (configFile.Exists)
try
{
bool isRunningOutOfProcess = IsRunningOutOfProcess();
Initialize(componentType);
}
catch (Exception e)
{
Trace.WriteLine("Error configuring application context for COM component of type " + componentType + ": " + e);
throw;
}
#if NET_2_0
ExeConfigurationSystem comConfig = new ExeConfigurationSystem(configFile.FullName);
isInitialized = true;
}
}
if (isRunningOutOfProcess)
private static void Initialize(Type componentType)
{
// this is to ensure, that assemblies placed next to the component assembly can be loaded
// even when they are not strong named.
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
FileInfo componentAssemblyFile = new FileInfo(componentType.Assembly.Location);
FileInfo assemblyFile = new FileInfo(componentAssemblyFile.FullName);
bool isRunningOutOfProcess = IsRunningOutOfProcess();
FileInfo configFile = new FileInfo(componentAssemblyFile.FullName + ".config");
// no config file and in-proc -> reuse app's context, error otherwise
if (!configFile.Exists)
{
if (!isRunningOutOfProcess)
{
// check for context with component's name
if (ContextRegistry.IsContextRegistered(componentType.Name))
{
Trace.WriteLine(string.Format("configuring COM OutProc Server '{0}' using '{1}'", componentAssemblyFile.FullName, componentAssemblyFile.FullName + ".config"));
// make the config "global"
ConfigurationUtils.SetConfigurationSystem(comConfig, true);
_appContext = ContextRegistry.GetContext();
if (_appContext == null)
{
throw ConfigurationUtils.CreateConfigurationException("Spring-exported COM components require <spring/context> section");
}
}
Trace.WriteLine(string.Format("configuring COM InProc Server '{0}' using section <spring/context name={1}> from app.config", componentAssemblyFile.FullName, componentType.Name));
_appContext = ContextRegistry.GetContext(componentType.Name);
}
else
{
Trace.WriteLine(string.Format("configuring COM InProc Server '{0}' using section <spring/context> from file '{1}'", componentAssemblyFile.FullName, componentAssemblyFile.FullName + ".config"));
_appContext = (IApplicationContext)comConfig.GetSection("spring/context");
if (_appContext == null)
{
throw ConfigurationUtils.CreateConfigurationException("Spring-exported COM components require <spring/context> section in configuration file");
}
Trace.WriteLine(string.Format("configuring COM InProc Server '{0}' using section <spring/context> from file '{1}'", componentAssemblyFile.FullName, configFile.FullName));
_appContext = ContextRegistry.GetContext();
}
#else
_appContext = (IApplicationContext) ConfigurationReader.GetSection(new FileSystemResource(configFile.FullName + ".config"),"spring/context");
if (_appContext == null)
{
throw ConfigurationUtils.CreateConfigurationException("Spring-exported COM components require <spring/context> section in configuration file");
}
#endif
}
else
{
Trace.WriteLine(string.Format("No configuration file '{0}' for COM component '{1}' found - bypassing configuration", componentAssemblyFile.FullName + ".config", componentAssemblyFile.FullName));
return;
}
throw ConfigurationUtils.CreateConfigurationException("Spring-exported COM components require <spring/context> section in configuration file '" + configFile.FullName + "'");
}
// set and switch to component assembly's directory (affects resolving relative paths during context instantiation!)
componentDirectory = componentAssemblyFile.Directory.FullName;
Environment.CurrentDirectory = componentDirectory;
if (isRunningOutOfProcess)
{
#if NET_2_0
Trace.WriteLine(string.Format("configuring COM OutProc Server '{0}' using '{1}'", componentAssemblyFile.FullName, configFile.FullName));
// read in config file
ExeConfigurationSystem comConfig = new ExeConfigurationSystem(assemblyFile.FullName);
// make the config "global" for this process, replacing any
// existing configuration that might already have been loaded
ConfigurationUtils.SetConfigurationSystem(comConfig, true);
_appContext = ContextRegistry.GetContext();
#else
_appContext = (IApplicationContext) ConfigurationReader.GetSection(new FileSystemResource(configFile.FullName),"spring/context");
#endif
}
else
{
Trace.WriteLine(string.Format("configuring COM InProc Server '{0}' using section <spring/context> from file '{1}'", componentAssemblyFile.FullName, configFile.FullName));
_appContext = (IApplicationContext)ConfigurationReader.GetSection(new FileSystemResource(configFile.FullName), "spring/context");
}
if (_appContext == null)
{
throw ConfigurationUtils.CreateConfigurationException("Spring-exported COM components require <spring/context> section in configuration file");
}
Trace.WriteLine(string.Format("completed configuring COM Component '{0}' using '{1}'", componentAssemblyFile.FullName, configFile.FullName));
}
private static bool IsRunningOutOfProcess()
@@ -128,6 +149,7 @@ namespace Spring.EnterpriseServices
// TODO: checkout a prob. better way to find out, whether we are executing as a com server or library
return AppDomain.CurrentDomain.SetupInformation.ApplicationName == "dllhost.exe";
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
string name = args.Name.Split(',')[0];
@@ -142,11 +164,16 @@ namespace Spring.EnterpriseServices
public static object GetObject(ServicedComponent sender, string targetName)
{
EnsureComponentContextRegistryInitialized(sender.GetType());
if (_appContext == null)
try
{
throw ConfigurationUtils.CreateConfigurationException("Spring-exported COM components require <spring/context> section in configuration file");
return _appContext.GetObject(targetName);
}
catch (Exception e)
{
Trace.WriteLine("Error configuring application context for COM component of type " + sender.GetType() + ": " + e);
throw;
}
return _appContext.GetObject(targetName);
}
}
}