fixed SPRNET-1379, Calculator EnterpriseService example
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<spring>
|
||||
<context>
|
||||
<resource uri="Config/services.xml" />
|
||||
</context>
|
||||
</spring>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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 <spring/context> configuration sections for <see cref="ServicedComponent"/>s
|
||||
/// generated by <see cref="EnterpriseServicesExporter"/>.
|
||||
/// Handles loading of <spring/context> 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
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user