diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs index c45e1773..db9e6331 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs @@ -25,7 +25,7 @@ using System.Collections; using System.Collections.Specialized; using System.Globalization; using System.Reflection; - +using System.Runtime.Remoting; using Common.Logging; using Spring.Collections; using Spring.Core; @@ -240,11 +240,9 @@ namespace Spring.Objects.Factory.Support // clear return type found: all factory methods return same type... return (Type)ObjectUtils.EnumerateFirstElement(returnTypes); } - else - { - // ambiguous return types found: return null to indicate "not determinable"... - return null; - } + + // ambiguous return types found: return null to indicate "not determinable"... + return null; } /// @@ -476,11 +474,9 @@ namespace Spring.Objects.Factory.Support throw new ObjectCreationException(definition.ResourceDescription, name, "Cannot apply property values to null instance."); } - else - { - // skip property population phase for null instance - return; - } + + // skip property population phase for null instance + return; } if (definition.ResolvedAutowireMode == AutoWiringMode.ByName || definition.ResolvedAutowireMode == AutoWiringMode.ByType) @@ -932,7 +928,7 @@ namespace Spring.Objects.Factory.Support } /// - /// Creates an instance from the passed in + /// Creates an instance from the passed in /// using constructor /// /// The name of the object to create - used for error messages. @@ -1448,213 +1444,221 @@ namespace Spring.Objects.Factory.Support } } - /// - /// Given a property value, return a value, resolving any references to other - /// objects in the factory if necessary. - /// - /// - ///

- /// The value could be : - /// - /// - ///

- /// An , - /// which leads to the creation of a corresponding new object instance. - /// Singleton flags and names of such "inner objects" are always ignored: inner objects - /// are anonymous prototypes. - ///

- /// - /// - ///

- /// A , which must - /// be resolved. - ///

- ///
- /// - ///

- /// An . This is a - /// special placeholder collection that may contain - /// s or - /// collections that will need to be resolved. - ///

- ///
- /// - ///

- /// An ordinary object or , in which case it's left alone. - ///

- ///
- /// - ///

- ///
- /// - /// The name of the object that is having the value of one of its properties resolved. - /// - /// - /// The definition of the named object. - /// - /// - /// The name of the property the value of which is being resolved. - /// - /// - /// The value of the property that is being resolved. - /// - protected object ResolveValueIfNecessary(string name, RootObjectDefinition definition, string argumentName, object argumentValue) - { - object resolvedValue = null; - // we must check the argument value to see whether it requires a runtime - // reference to another object to be resolved. - // if it does, we'll attempt to instantiate the object and set the reference. - if (argumentValue is ObjectDefinitionHolder) - { - // contains an IObjectDefinition with name and aliases... - ObjectDefinitionHolder holder = (ObjectDefinitionHolder)argumentValue; - resolvedValue = ResolveInnerObjectDefinition(name, holder.ObjectName, argumentName, holder.ObjectDefinition, definition.IsSingleton); - } - else if (argumentValue is IObjectDefinition) - { - // resolve plain IObjectDefinition, without contained name: use dummy name... - IObjectDefinition def = (IObjectDefinition)argumentValue; - resolvedValue = ResolveInnerObjectDefinition(name, "(inner object)", argumentName, def, definition.IsSingleton); + ///// + ///// Given a property value, return a value, resolving any references to other + ///// objects in the factory if necessary. + ///// + ///// + /////

+ ///// The value could be : + ///// + ///// + /////

+ ///// An , + ///// which leads to the creation of a corresponding new object instance. + ///// Singleton flags and names of such "inner objects" are always ignored: inner objects + ///// are anonymous prototypes. + /////

+ ///// + ///// + /////

+ ///// A , which must + ///// be resolved. + /////

+ /////
+ ///// + /////

+ ///// An . This is a + ///// special placeholder collection that may contain + ///// s or + ///// collections that will need to be resolved. + /////

+ /////
+ ///// + /////

+ ///// An ordinary object or , in which case it's left alone. + /////

+ /////
+ ///// + /////

+ /////
+ ///// + ///// The name of the object that is having the value of one of its properties resolved. + ///// + ///// + ///// The definition of the named object. + ///// + ///// + ///// The name of the property the value of which is being resolved. + ///// + ///// + ///// The value of the property that is being resolved. + ///// +// protected object ResolveValueIfNecessary(string name, RootObjectDefinition definition, string argumentName, object argumentValue) +// { +// object resolvedValue = null; +// +// AssertUtils.ArgumentNotNull(resolvedValue, "test"); +// +// // we must check the argument value to see whether it requires a runtime +// // reference to another object to be resolved. +// // if it does, we'll attempt to instantiate the object and set the reference. +// if (RemotingServices.IsTransparentProxy(argumentValue)) +// { +// resolvedValue = argumentValue; +// } +// else if (argumentValue is ObjectDefinitionHolder) +// { +// // contains an IObjectDefinition with name and aliases... +// ObjectDefinitionHolder holder = (ObjectDefinitionHolder)argumentValue; +// resolvedValue = ResolveInnerObjectDefinition(name, holder.ObjectName, argumentName, holder.ObjectDefinition, definition.IsSingleton); +// } +// else if (argumentValue is IObjectDefinition) +// { +// // resolve plain IObjectDefinition, without contained name: use dummy name... +// IObjectDefinition def = (IObjectDefinition)argumentValue; +// resolvedValue = ResolveInnerObjectDefinition(name, "(inner object)", argumentName, def, definition.IsSingleton); +// +// } +// else if (argumentValue is RuntimeObjectReference) +// { +// RuntimeObjectReference roref = (RuntimeObjectReference)argumentValue; +// resolvedValue = ResolveReference(definition, name, argumentName, roref); +// } +// else if (argumentValue is ExpressionHolder) +// { +// ExpressionHolder expHolder = (ExpressionHolder)argumentValue; +// object context = null; +// IDictionary variables = null; +// +// if (expHolder.Properties != null) +// { +// PropertyValue contextProperty = expHolder.Properties.GetPropertyValue("Context"); +// context = contextProperty == null +// ? null +// : ResolveValueIfNecessary2(name, definition, "Context", +// contextProperty.Value); +// PropertyValue variablesProperty = expHolder.Properties.GetPropertyValue("Variables"); +// object vars = (variablesProperty == null +// ? null +// : ResolveValueIfNecessary2(name, definition, "Variables", +// variablesProperty.Value)); +// if (vars is IDictionary) +// { +// variables = (IDictionary)vars; +// } +// else +// { +// if (vars != null) throw new ArgumentException("'Variables' must resolve to an IDictionary"); +// } +// } +// +// if (variables == null) variables = CollectionsUtil.CreateCaseInsensitiveHashtable(); +// // add 'this' objectfactory reference to variables +// variables.Add(Expression.ReservedVariableNames.CurrentObjectFactory, this); +// +// resolvedValue = expHolder.Expression.GetValue(context, variables); +// } +// else if (argumentValue is IManagedCollection) +// { +// resolvedValue = +// ((IManagedCollection)argumentValue).Resolve(name, definition, argumentName, +// new ManagedCollectionElementResolver(ResolveValueIfNecessary2)); +// } +// else if (argumentValue is TypedStringValue) +// { +// TypedStringValue tsv = (TypedStringValue)argumentValue; +// try +// { +// Type resolvedTargetType = ResolveTargetType(tsv); +// if (resolvedTargetType != null) +// { +// resolvedValue = TypeConversionUtils.ConvertValueIfNecessary(tsv.TargetType, tsv.Value, null); +// } +// else +// { +// resolvedValue = tsv.Value; +// } +// } +// catch (Exception ex) +// { +// throw new ObjectCreationException(definition.ResourceDescription, name, +// "Error converted typed String value for " + argumentName, ex); +// } +// +// } +// else +// { +// // no need to resolve value... +// resolvedValue = argumentValue; +// } +// return resolvedValue; +// } - } - else if (argumentValue is RuntimeObjectReference) - { - RuntimeObjectReference roref = (RuntimeObjectReference)argumentValue; - resolvedValue = ResolveReference(definition, name, argumentName, roref); - } - else if (argumentValue is ExpressionHolder) - { - ExpressionHolder expHolder = (ExpressionHolder)argumentValue; - object context = null; - IDictionary variables = null; + ///// + ///// Resolve the target type of the passed . + ///// + ///// The who's target type is to be resolved + ///// The resolved target type, if any. otherwise. +// protected virtual Type ResolveTargetType(TypedStringValue value) +// { +// if (value.HasTargetType) +// { +// return value.TargetType; +// } +// else +// { +// return null; +// } +// } - if (expHolder.Properties != null) - { - PropertyValue contextProperty = expHolder.Properties.GetPropertyValue("Context"); - context = contextProperty == null - ? null - : ResolveValueIfNecessary(name, definition, "Context", - contextProperty.Value); - PropertyValue variablesProperty = expHolder.Properties.GetPropertyValue("Variables"); - object vars = (variablesProperty == null - ? null - : ResolveValueIfNecessary(name, definition, "Variables", - variablesProperty.Value)); - if (vars is IDictionary) - { - variables = (IDictionary)vars; - } - else - { - if (vars != null) throw new ArgumentException("'Variables' must resolve to an IDictionary"); - } - } - - if (variables == null) variables = CollectionsUtil.CreateCaseInsensitiveHashtable(); - // add 'this' objectfactory reference to variables - variables.Add(Expression.ReservedVariableNames.CurrentObjectFactory, this); - - resolvedValue = expHolder.Expression.GetValue(context, variables); - } - else if (argumentValue is IManagedCollection) - { - resolvedValue = - ((IManagedCollection)argumentValue).Resolve(name, definition, argumentName, - new ManagedCollectionElementResolver(ResolveValueIfNecessary)); - } - else if (argumentValue is TypedStringValue) - { - TypedStringValue tsv = (TypedStringValue)argumentValue; - try - { - Type resolvedTargetType = ResolveTargetType(tsv); - if (resolvedTargetType != null) - { - resolvedValue = TypeConversionUtils.ConvertValueIfNecessary(tsv.TargetType, tsv.Value, null); - } - else - { - resolvedValue = tsv.Value; - } - } - catch (Exception ex) - { - throw new ObjectCreationException(definition.ResourceDescription, name, - "Error converted typed String value for " + argumentName, ex); - } - - } - else - { - // no need to resolve value... - resolvedValue = argumentValue; - } - return resolvedValue; - } - - /// - /// Resolve the target type of the passed . - /// - /// The who's target type is to be resolved - /// The resolved target type, if any. otherwise. - protected virtual Type ResolveTargetType(TypedStringValue value) - { - if (value.HasTargetType) - { - return value.TargetType; - } - else - { - return null; - } - } - /// - /// Resolves an inner object definition. - /// - /// - /// The name of the object that surrounds this inner object definition. - /// - /// - /// The name of the inner object definition... note: this is a synthetic - /// name assigned by the factory (since it makes no sense for inner object - /// definitions to have names). - /// - /// - /// The name of the property the value of which is being resolved. - /// - /// - /// The definition of the inner object that is to be resolved. - /// - /// - /// if the owner of the property is a singleton. - /// - /// - /// The resolved object as defined by the inner object definition. - /// - protected object ResolveInnerObjectDefinition(string name, string innerObjectName, string argumentName, IObjectDefinition definition, - bool singletonOwner) - { - RootObjectDefinition mod = GetMergedObjectDefinition(innerObjectName, definition); - mod.IsSingleton = singletonOwner; - object instance; - object result; - try - { - instance = InstantiateObject(innerObjectName, mod, ObjectUtils.EmptyObjects, false, false); - result = GetObjectForInstance(innerObjectName, instance); - } - catch (ObjectsException ex) - { - throw ObjectCreationException.GetObjectCreationException(ex, name, argumentName, definition.ResourceDescription, innerObjectName); - } - if (singletonOwner && instance is IDisposable) - { - // keep a reference to the inner object instance, to be able to destroy - // it on factory shutdown... - DisposableInnerObjects.Add(instance); - } - return result; - } + ///// + ///// Resolves an inner object definition. + ///// + ///// + ///// The name of the object that surrounds this inner object definition. + ///// + ///// + ///// The name of the inner object definition... note: this is a synthetic + ///// name assigned by the factory (since it makes no sense for inner object + ///// definitions to have names). + ///// + ///// + ///// The name of the property the value of which is being resolved. + ///// + ///// + ///// The definition of the inner object that is to be resolved. + ///// + ///// + ///// if the owner of the property is a singleton. + ///// + ///// + ///// The resolved object as defined by the inner object definition. + ///// +// protected object ResolveInnerObjectDefinition(string name, string innerObjectName, string argumentName, IObjectDefinition definition, +// bool singletonOwner) +// { +// RootObjectDefinition mod = GetMergedObjectDefinition(innerObjectName, definition); +// mod.IsSingleton = singletonOwner; +// object instance; +// object result; +// try +// { +// instance = InstantiateObject(innerObjectName, mod, ObjectUtils.EmptyObjects, false, false); +// result = GetObjectForInstance(innerObjectName, instance); +// } +// catch (ObjectsException ex) +// { +// throw ObjectCreationException.GetObjectCreationException(ex, name, argumentName, definition.ResourceDescription, innerObjectName); +// } +// if (singletonOwner && instance is IDisposable) +// { +// // keep a reference to the inner object instance, to be able to destroy +// // it on factory shutdown... +// DisposableInnerObjects.Add(instance); +// } +// return result; +// } /// /// Resolve a reference to another object in the factory. @@ -1899,12 +1903,10 @@ namespace Spring.Objects.Factory.Support { return AutowireConstructor(type.Name, rod, null, null).WrappedInstance; } - else - { - object obj = InstantiationStrategy.Instantiate(rod, string.Empty, this); - PopulateObject(obj.GetType().Name, rod, new ObjectWrapper(obj)); - return obj; - } + + object obj = InstantiationStrategy.Instantiate(rod, string.Empty, this); + PopulateObject(obj.GetType().Name, rod, new ObjectWrapper(obj)); + return obj; } /// @@ -1936,6 +1938,7 @@ namespace Spring.Objects.Factory.Support { throw new ArgumentException("Just AutoWiringMode.ByName and AutoWiringMode.ByType allowed."); } + RootObjectDefinition rod = new RootObjectDefinition(instance.GetType(), autowireMode, dependencyCheck); PopulateObject(instance.GetType().Name, rod, new ObjectWrapper(instance)); } diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionValueResolver.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionValueResolver.cs index 98ad0da4..1081610c 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionValueResolver.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionValueResolver.cs @@ -21,6 +21,7 @@ using System; using System.Collections; using System.Collections.Specialized; +using System.Runtime.Remoting; using Spring.Core.TypeConversion; using Spring.Core.TypeResolution; using Spring.Expressions; @@ -115,7 +116,11 @@ namespace Spring.Objects.Factory.Support // we must check the argument value to see whether it requires a runtime // reference to another object to be resolved. // if it does, we'll attempt to instantiate the object and set the reference. - if (argumentValue is ObjectDefinitionHolder) + if (RemotingServices.IsTransparentProxy(argumentValue)) + { + resolvedValue = argumentValue; + } + else if (argumentValue is ObjectDefinitionHolder) { // contains an IObjectDefinition with name and aliases... ObjectDefinitionHolder holder = (ObjectDefinitionHolder)argumentValue; diff --git a/test/Spring/Spring.Services.Tests/Data/Spring/Remoting/saoSingleton-autowired.xml b/test/Spring/Spring.Services.Tests/Data/Spring/Remoting/saoSingleton-autowired.xml new file mode 100644 index 00000000..5c6b3dbd --- /dev/null +++ b/test/Spring/Spring.Services.Tests/Data/Spring/Remoting/saoSingleton-autowired.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/Spring/Spring.Services.Tests/Remoting/SaoFactoryObjectTests.cs b/test/Spring/Spring.Services.Tests/Remoting/SaoFactoryObjectTests.cs index 3cc5b6eb..b4196916 100644 --- a/test/Spring/Spring.Services.Tests/Remoting/SaoFactoryObjectTests.cs +++ b/test/Spring/Spring.Services.Tests/Remoting/SaoFactoryObjectTests.cs @@ -21,6 +21,7 @@ #region Imports using System; +using System.Diagnostics; using System.Runtime.Remoting; using System.Runtime.Remoting.Lifetime; using NUnit.Framework; @@ -28,6 +29,7 @@ using Spring.Aop.Framework; using Spring.Context; using Spring.Context.Support; using Spring.Objects; +using Spring.Objects.Factory.Config; using Spring.Objects.Factory.Xml; #endregion @@ -92,6 +94,84 @@ namespace Spring.Remoting sc.Count(); Assert.AreEqual(2, sc.Counter, "Remote object doesn't work in a 'Singleton' mode."); } + + public class SPRNET967_SimpleCounterWrapper : MarshalByRefObject, ISimpleCounter + { + private ISimpleCounter service; + + public SPRNET967_SimpleCounterWrapper() + {} + + public SPRNET967_SimpleCounterWrapper(ISimpleCounter service) + { + this.service = service; + } + + public ISimpleCounter Service + { + get { return service; } + set { service = value; } + } + + public int Counter + { + get { return service.Counter; } + set { service.Counter = value; } + } + + public void Count() + { + service.Count(); + } + } + + public class SPRNET967_SimpleCounterClient + { + private ISimpleCounter service; + + public SPRNET967_SimpleCounterClient() + {} + + public SPRNET967_SimpleCounterClient(ISimpleCounter service) + { + this.service = service; + } + + public ISimpleCounter Service + { + get { return service; } + set { service = value; } + } + + public int Counter + { + get { return service.Counter; } + set { service.Counter = value; } + } + + public void Count() + { + service.Count(); + } + } + + [Test] + public void GetSaoWithSingletonModeAutowired_SPRNET967() + { + // register server by hand to avoid duplicate interfaces + SPRNET967_SimpleCounterWrapper svr = new SPRNET967_SimpleCounterWrapper( new SimpleCounter(1) ); + RemotingServices.Marshal(svr, "RemotedSaoSingletonCounter"); + +// object svc = Activator.GetObject(typeof(ISimpleCounter), "tcp://localhost:8005/RemotedSaoSingletonCounter"); +// Assert.IsTrue( svc is IObjectDefinition ); +// Assert.IsTrue( svc is ISimpleCounter ); + + IApplicationContext ctx = new XmlApplicationContext("assembly://Spring.Services.Tests/Spring.Data.Spring.Remoting/saoSingleton-autowired.xml"); + ContextRegistry.RegisterContext(ctx); + SPRNET967_SimpleCounterClient client = (SPRNET967_SimpleCounterClient) ctx.GetObject("counterClient"); + client.Count(); + Assert.AreEqual(2, client.Counter); + } [Test] public void GetSaoWithSingletonModeAndAop() diff --git a/test/Spring/Spring.Services.Tests/Spring.Services.Tests.2008.csproj b/test/Spring/Spring.Services.Tests/Spring.Services.Tests.2008.csproj index e7911834..eb2dcff1 100644 --- a/test/Spring/Spring.Services.Tests/Spring.Services.Tests.2008.csproj +++ b/test/Spring/Spring.Services.Tests/Spring.Services.Tests.2008.csproj @@ -1,7 +1,7 @@  Local - 9.0.21022 + 9.0.30729 2.0 {4374F018-9738-46BF-A399-4594CEE75B21} Debug @@ -181,6 +181,12 @@ + + + + + +