From 19fd1876d84050caffa383ab04360c919db6f510 Mon Sep 17 00:00:00 2001 From: Steve Bohlen Date: Wed, 18 Jul 2012 10:29:42 -0400 Subject: [PATCH] SPRNET-1514 adding DelegatingFactoryObject and related tests --- .../Support/DelegatingFactoryObject.cs | 93 +++++++++++++++++++ .../Spring.Core/Spring.Core.2008.csproj | 1 + .../Spring.Core/Spring.Core.2010.csproj | 1 + .../Support/DelegatingFactoryObjectTests.cs | 78 ++++++++++++++++ .../Spring.Core.Tests.2008.csproj | 1 + .../Spring.Core.Tests.2010.csproj | 1 + 6 files changed, 175 insertions(+) create mode 100644 src/Spring/Spring.Core/Objects/Factory/Support/DelegatingFactoryObject.cs create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Support/DelegatingFactoryObjectTests.cs diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/DelegatingFactoryObject.cs b/src/Spring/Spring.Core/Objects/Factory/Support/DelegatingFactoryObject.cs new file mode 100644 index 00000000..22971e80 --- /dev/null +++ b/src/Spring/Spring.Core/Objects/Factory/Support/DelegatingFactoryObject.cs @@ -0,0 +1,93 @@ +#region License + +/* + * Copyright © 2002-2011 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 + +using System; + +namespace Spring.Objects.Factory.Support +{ + /// + /// Convenience implementation of the interface that + /// delegates to an arbitrary object + method to perform the object construction. + /// + /// + /// + /// Because this implementation requires a delegate + /// passed to its ctor, its only possible to configure this object and register + /// it with the via code rather than via XML. + /// + /// + /// + public class DelegatingFactoryObject : IFactoryObject + { + private readonly bool _isSingleton; + private readonly Func _builderDelegate; + + + /// + /// Initializes a new instance of the class. + /// + /// The builder delegate. + /// if set to true [is singleton]. + public DelegatingFactoryObject(Func builderDelegate, bool isSingleton) + { + _builderDelegate = builderDelegate; + _isSingleton = isSingleton; + } + + + /// + /// Return an instance (possibly shared or independent) of the object + /// managed by this factory. + /// + /// + /// If this method is being called in the context of an enclosing IoC container and + /// returns , the IoC container will consider this factory + /// object as not being fully initialized and throw a corresponding (and most + /// probably fatal) exception. + /// + /// + /// + /// An instance (possibly shared or independent) of the object managed by + /// this factory. + /// + public object GetObject() + { + return _builderDelegate.Invoke(); + } + + /// + /// Return the of object that this + /// creates, or + /// if not known in advance. + /// + public Type ObjectType + { + get { return typeof(T); } + } + + /// + /// Is the object managed by this factory a singleton or a prototype? + /// + public bool IsSingleton + { + get { return _isSingleton; } + } + } +} \ No newline at end of file diff --git a/src/Spring/Spring.Core/Spring.Core.2008.csproj b/src/Spring/Spring.Core/Spring.Core.2008.csproj index 41e0f086..65f78ae3 100644 --- a/src/Spring/Spring.Core/Spring.Core.2008.csproj +++ b/src/Spring/Spring.Core/Spring.Core.2008.csproj @@ -708,6 +708,7 @@ + diff --git a/src/Spring/Spring.Core/Spring.Core.2010.csproj b/src/Spring/Spring.Core/Spring.Core.2010.csproj index f90b0927..d734761b 100644 --- a/src/Spring/Spring.Core/Spring.Core.2010.csproj +++ b/src/Spring/Spring.Core/Spring.Core.2010.csproj @@ -710,6 +710,7 @@ + diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Support/DelegatingFactoryObjectTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/DelegatingFactoryObjectTests.cs new file mode 100644 index 00000000..e1597777 --- /dev/null +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/DelegatingFactoryObjectTests.cs @@ -0,0 +1,78 @@ +using NUnit.Framework; +using Spring.Context; +using Spring.Context.Support; + +namespace Spring.Objects.Factory.Support +{ + [TestFixture] + public class DelegatingFactoryObjectTests + { + [SetUp] + public void _TestSetUp() + { + var context = new GenericApplicationContext(); + ContextRegistry.Clear(); + ContextRegistry.RegisterContext(context); + } + + private void RegisterDelegatingFactoryWithContext(bool buildSingletonObjectsWhenInvoked) + { + var targetBuilder = new ThingThatBuildsTargets(); + var factory = new DelegatingFactoryObject(targetBuilder.BuildTarget, buildSingletonObjectsWhenInvoked); + + Assume.That(ContextRegistry.GetContext(), Is.InstanceOf(), "test requires a registered context that implements IConfigurableApplicationContext!"); + + var ctx = (IConfigurableApplicationContext)ContextRegistry.GetContext(); + ctx.ObjectFactory.RegisterSingleton("target", factory); + } + + [Test] + public void CanReturnSingletonObjects() + { + RegisterDelegatingFactoryWithContext(true); + + var targetObject1 = ContextRegistry.GetContext().GetObject(); + var targetObject2 = ContextRegistry.GetContext().GetObject(); + + Assert.That(targetObject1, Is.SameAs(targetObject2)); + Assert.That(targetObject1.Counter, Is.EqualTo(targetObject2.Counter)); + } + + [Test] + public void CanReturnProtoypeObjects() + { + RegisterDelegatingFactoryWithContext(false); + + var targetObject1 = ContextRegistry.GetContext().GetObject(); + var targetObject2 = ContextRegistry.GetContext().GetObject(); + + Assert.That(targetObject1, Is.Not.SameAs(targetObject2)); + Assert.That(targetObject1.Counter, Is.Not.EqualTo(targetObject2.Counter)); + } + + } + + public class ThingThatBuildsTargets + { + //since the IFactoryObject impl that contains this is registered w context as singleton, + // this counter is effectively static (sort of! ) and will be incremented on each call to build the TARGET instance + private int _counter; + + public TargetToBuild BuildTarget() + { + //create and return a new TARGET instance with the incremented counter value to show its working + return new TargetToBuild(_counter++); + } + } + + //the type we're trying to tell the container we want to be in charge of creating + public class TargetToBuild + { + public TargetToBuild(int counter) + { + Counter = counter; + } + + public int Counter { get; private set; } + } +} \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj index 1170990a..25131925 100644 --- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj +++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj @@ -335,6 +335,7 @@ + diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj index 9650a7cb..9a00d45b 100644 --- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj +++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj @@ -358,6 +358,7 @@ + Code