From: <jer...@us...> - 2007-03-26 01:52:42
|
Revision: 29 http://structuremap.svn.sourceforge.net/structuremap/?rev=29&view=rev Author: jeremydmiller Date: 2007-03-25 18:52:39 -0700 (Sun, 25 Mar 2007) Log Message: ----------- Adding some defensive programming to the Fluent Interface API Modified Paths: -------------- trunk/Source/StructureMap/Configuration/DSL/ChildInstanceExpression.cs trunk/Source/StructureMap/Configuration/DSL/CreatePluginFamilyExpression.cs trunk/Source/StructureMap/Configuration/DSL/IMementoBuilder.cs trunk/Source/StructureMap/Configuration/DSL/InstanceDefaultExpression.cs trunk/Source/StructureMap/Configuration/DSL/InstanceExpression.cs trunk/Source/StructureMap/Configuration/DSL/LiteralExpression.cs trunk/Source/StructureMap/Configuration/DSL/MementoBuilder.cs trunk/Source/StructureMap/Configuration/DSL/PrototypeExpression.cs trunk/Source/StructureMap/Graph/Plugin.cs trunk/Source/StructureMap/StructureMapException.resx trunk/Source/StructureMap.Testing/Configuration/DSL/CreatePluginFamilyTester.cs trunk/Source/StructureMap.Testing/Configuration/DSL/InstanceExpressionTester.cs Added Paths: ----------- trunk/Source/StructureMap/Configuration/DSL/ExpressionValidator.cs trunk/Source/StructureMap.Testing/Configuration/DSL/ChildInstanceExpressionTester.cs Modified: trunk/Source/StructureMap/Configuration/DSL/ChildInstanceExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/ChildInstanceExpression.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap/Configuration/DSL/ChildInstanceExpression.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -21,7 +21,13 @@ _propertyName = propertyName; } + public ChildInstanceExpression(InstanceExpression instance, MemoryInstanceMemento memento, string propertyName, Type childType) + : this(instance, memento, propertyName) + { + _childType = childType; + } + public InstanceExpression IsNamedInstance(string instanceKey) { MemoryInstanceMemento child = MemoryInstanceMemento.CreateReferencedInstanceMemento(instanceKey); @@ -30,9 +36,11 @@ return _instance; } - // TODO -- negative case if the concrete type cannot be an implicit instance public InstanceExpression IsConcreteType<T>() { + Type pluggedType = typeof (T); + ExpressionValidator.ValidatePluggabilityOf(pluggedType).IntoPluginType(_childType); + InstanceExpression child = new InstanceExpression(_childType); child.UsingConcreteType<T>(); _children.Add(child); @@ -70,6 +78,11 @@ public InstanceExpression Is(InstanceExpression child) { + if (child.PluggedType != null && _childType != null) + { + ExpressionValidator.ValidatePluggabilityOf(child.PluggedType).IntoPluginType(_childType); + } + _children.Add(child); MemoryInstanceMemento childMemento = MemoryInstanceMemento.CreateReferencedInstanceMemento(child.InstanceKey); Modified: trunk/Source/StructureMap/Configuration/DSL/CreatePluginFamilyExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/CreatePluginFamilyExpression.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap/Configuration/DSL/CreatePluginFamilyExpression.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -19,7 +19,7 @@ _pluginType = pluginType; } - public void Configure(PluginGraph graph) + void IExpression.Configure(PluginGraph graph) { PluginFamily family = graph.LocateOrCreateFamilyForType(_pluginType); InterceptorChainBuilder builder = new InterceptorChainBuilder(); @@ -36,26 +36,10 @@ graph.Assemblies.Add(assembly); } - public CreatePluginFamilyExpression WithDefaultConcreteType<T>() - { - Plugin plugin = addPlugin<T>(); - - _alterations.Add(delegate(PluginFamily family) { family.DefaultInstanceKey = plugin.ConcreteKey; }); - - return this; - } - - private Plugin addPlugin<T>() - { - Plugin plugin = Plugin.CreateImplicitPlugin(typeof (T)); - - _alterations.Add(delegate(PluginFamily family) { family.Plugins.Add(plugin); }); - - return plugin; - } - public CreatePluginFamilyExpression TheDefaultIs(IMementoBuilder builder) { + builder.ValidatePluggability(_pluginType); + _alterations.Add(delegate(PluginFamily family) { InstanceMemento memento = builder.BuildMemento(family); @@ -68,6 +52,8 @@ public CreatePluginFamilyExpression TheDefaultIsConcreteType<T>() { + ExpressionValidator.ValidatePluggabilityOf(typeof(T)).IntoPluginType(_pluginType); + _alterations.Add(delegate(PluginFamily family) { Plugin plugin = family.Plugins.FindOrCreate(typeof (T)); Added: trunk/Source/StructureMap/Configuration/DSL/ExpressionValidator.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/ExpressionValidator.cs (rev 0) +++ trunk/Source/StructureMap/Configuration/DSL/ExpressionValidator.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -0,0 +1,35 @@ +using System; +using StructureMap.Graph; + +namespace StructureMap.Configuration.DSL +{ + public static class ExpressionValidator + { + public static ValidateExpression ValidatePluggabilityOf(Type pluggedType) + { + return new ValidateExpression(pluggedType); + } + + + public class ValidateExpression + { + private readonly Type _pluggedType; + + public ValidateExpression(Type pluggedType) + { + _pluggedType = pluggedType; + } + + public void IntoPluginType(Type pluginType) + { + if (!Plugin.CanBeCast(pluginType, _pluggedType)) + { + throw new StructureMapException( + 303, + TypePath.GetAssemblyQualifiedName(_pluggedType), + TypePath.GetAssemblyQualifiedName(pluginType)); + } + } + } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap/Configuration/DSL/IMementoBuilder.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/IMementoBuilder.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap/Configuration/DSL/IMementoBuilder.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -1,3 +1,4 @@ +using System; using StructureMap.Graph; namespace StructureMap.Configuration.DSL @@ -7,5 +8,7 @@ InstanceMemento BuildMemento(PluginFamily family); InstanceMemento BuildMemento(PluginGraph graph); void SetInstanceName(string instanceKey); + + void ValidatePluggability(Type pluginType); } } \ No newline at end of file Modified: trunk/Source/StructureMap/Configuration/DSL/InstanceDefaultExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/InstanceDefaultExpression.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap/Configuration/DSL/InstanceDefaultExpression.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -22,7 +22,7 @@ return _parent; } - public void Configure(Profile profile, PluginGraph graph) + internal void Configure(Profile profile, PluginGraph graph) { if (!string.IsNullOrEmpty(_instanceKey)) { @@ -40,8 +40,10 @@ InstanceDefault instanceDefault = new InstanceDefault(_pluginType, defaultKey); profile.AddOverride(instanceDefault); } - - // TODO throw up!!! + else + { + throw new StructureMapException(304, TypePath.GetAssemblyQualifiedName(_pluginType)); + } } public ProfileExpression Use(IMementoBuilder mementoBuilder) Modified: trunk/Source/StructureMap/Configuration/DSL/InstanceExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/InstanceExpression.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap/Configuration/DSL/InstanceExpression.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -12,6 +12,12 @@ { } + + internal Type PluggedType + { + get { return _pluggedType; } + } + protected override void buildMemento() { _memento = new MemoryInstanceMemento(); @@ -75,8 +81,13 @@ public ChildInstanceExpression Child<T>() { - // TODO -- what if the property can't be found string propertyName = findPropertyName<T>(); + + if (string.IsNullOrEmpty(propertyName)) + { + throw new StructureMapException(305, TypePath.GetAssemblyQualifiedName(typeof (T))); + } + ChildInstanceExpression child = new ChildInstanceExpression(this, _memento, propertyName); addChildExpression(child); child.ChildType = typeof (T); @@ -88,5 +99,15 @@ Plugin plugin = Plugin.CreateImplicitPlugin(_pluggedType); return plugin.FindFirstConstructorArgumentOfType<T>(); } + + public override void ValidatePluggability(Type pluginType) + { + if (_pluggedType == null) + { + return; + } + + ExpressionValidator.ValidatePluggabilityOf(_pluggedType).IntoPluginType(pluginType); + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Configuration/DSL/LiteralExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/LiteralExpression.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap/Configuration/DSL/LiteralExpression.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -1,3 +1,4 @@ +using System; using StructureMap.Graph; namespace StructureMap.Configuration.DSL @@ -36,5 +37,10 @@ { _memento = new LiteralMemento(null); } + + public override void ValidatePluggability(Type pluginType) + { + ExpressionValidator.ValidatePluggabilityOf(_target.GetType()).IntoPluginType(pluginType); + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Configuration/DSL/MementoBuilder.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/MementoBuilder.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap/Configuration/DSL/MementoBuilder.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -88,6 +88,8 @@ _instanceKey = instanceKey; } + public abstract void ValidatePluggability(Type pluginType); + protected void addChildExpression(IExpression expression) { _children.Add(expression); Modified: trunk/Source/StructureMap/Configuration/DSL/PrototypeExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/PrototypeExpression.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap/Configuration/DSL/PrototypeExpression.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -37,5 +37,10 @@ { _memento = new PrototypeMemento(string.Empty, (ICloneable) _prototype); } + + public override void ValidatePluggability(Type pluginType) + { + ExpressionValidator.ValidatePluggabilityOf(_prototype.GetType()).IntoPluginType(pluginType); + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/Plugin.cs =================================================================== --- trunk/Source/StructureMap/Graph/Plugin.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap/Graph/Plugin.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -82,6 +82,11 @@ /// <returns></returns> public static bool CanBeCast(Type pluginType, Type pluggedType) { + if (pluggedType.IsInterface || pluggedType.IsAbstract) + { + return false; + } + if (GenericsPluginGraph.CanBeCast(pluginType, pluggedType)) { return true; Modified: trunk/Source/StructureMap/StructureMapException.resx =================================================================== --- trunk/Source/StructureMap/StructureMapException.resx 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap/StructureMapException.resx 2007-03-26 01:52:39 UTC (rev 29) @@ -237,4 +237,13 @@ <data name="302" xml:space="preserve"> <value>There is no argument of type {0} for concrete type {1}</value> </data> + <data name="303" xml:space="preserve"> + <value>Type {0} is either abstract or cannot be plugged into Type {1}</value> + </data> + <data name="304" xml:space="preserve"> + <value>Profile or Machine default for {0} not completely specified</value> + </data> + <data name="305" xml:space="preserve"> + <value>There is no constructor property found of type {0}</value> + </data> </root> \ No newline at end of file Added: trunk/Source/StructureMap.Testing/Configuration/DSL/ChildInstanceExpressionTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Configuration/DSL/ChildInstanceExpressionTester.cs (rev 0) +++ trunk/Source/StructureMap.Testing/Configuration/DSL/ChildInstanceExpressionTester.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -0,0 +1,60 @@ +using NUnit.Framework; +using StructureMap.Configuration.DSL; +using StructureMap.Testing.Widget4; + +namespace StructureMap.Testing.Configuration.DSL +{ + [TestFixture] + public class ChildInstanceExpressionTester + { + [SetUp] + public void SetUp() + { + } + + [Test, ExpectedException(typeof(StructureMapException), "StructureMap Exception Code: 303\nType System.String,mscorlib is either abstract or cannot be plugged into Type StructureMap.Testing.Configuration.DSL.IType,StructureMap.Testing")] + public void CantCastTheRequestedConcreteType() + { + InstanceExpression instance = new InstanceExpression(typeof(IStrategy)); + MemoryInstanceMemento memento = new MemoryInstanceMemento(); + + ChildInstanceExpression expression = new ChildInstanceExpression(instance, memento, "a property", typeof(IType)); + expression.IsConcreteType<string>(); + } + + [Test, ExpectedException(typeof(StructureMapException), "StructureMap Exception Code: 303\nType StructureMap.Testing.Configuration.DSL.AbstractType,StructureMap.Testing is either abstract or cannot be plugged into Type StructureMap.Testing.Configuration.DSL.IType,StructureMap.Testing")] + public void CantCastTheRequestedConcreteType2() + { + InstanceExpression instance = new InstanceExpression(typeof(IStrategy)); + MemoryInstanceMemento memento = new MemoryInstanceMemento(); + + ChildInstanceExpression expression = new ChildInstanceExpression(instance, memento, "a property", typeof(IType)); + expression.IsConcreteType<AbstractType>(); + } + + + [Test, ExpectedException(typeof(StructureMapException), "StructureMap Exception Code: 303\nType StructureMap.Testing.Configuration.DSL.AbstractType,StructureMap.Testing is either abstract or cannot be plugged into Type StructureMap.Testing.Configuration.DSL.IType,StructureMap.Testing")] + public void CantCastTheRequestedPluggedType3() + { + InstanceExpression instance = new InstanceExpression(typeof(IStrategy)); + MemoryInstanceMemento memento = new MemoryInstanceMemento(); + + ChildInstanceExpression expression = new ChildInstanceExpression(instance, memento, "a property", typeof(IType)); + InstanceExpression child = new InstanceExpression(typeof(IType)).UsingConcreteType<AbstractType>(); + expression.Is(child); + } + } + + public interface IType + { + } + + public abstract class AbstractType : IType + { + } + + public class ConcreteType : AbstractType + { + + } +} \ No newline at end of file Modified: trunk/Source/StructureMap.Testing/Configuration/DSL/CreatePluginFamilyTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Configuration/DSL/CreatePluginFamilyTester.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap.Testing/Configuration/DSL/CreatePluginFamilyTester.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -17,6 +17,13 @@ } + [Test, ExpectedException(typeof(StructureMapException))] + public void TheConceteTypeDoesNotCase() + { + Registry registry = new Registry(); + registry.BuildInstancesOf<Rule>().TheDefaultIsConcreteType<IWidget>(); + } + [Test] public void TheDefaultInstanceIsConcreteType() { @@ -66,7 +73,7 @@ using (Registry registry = new Registry(pluginGraph)) { // Specify the default implementation for an interface - registry.BuildInstancesOf<IGateway>().WithDefaultConcreteType<StubbedGateway>(); + registry.BuildInstancesOf<IGateway>().TheDefaultIsConcreteType<StubbedGateway>(); } Assert.IsTrue(pluginGraph.PluginFamilies.Contains<IGateway>()); @@ -142,7 +149,7 @@ PluginGraph pluginGraph = new PluginGraph(); using (Registry registry = new Registry(pluginGraph)) { - registry.BuildInstancesOf<IGateway>().WithDefaultConcreteType<FakeGateway>(); + registry.BuildInstancesOf<IGateway>().TheDefaultIsConcreteType<FakeGateway>(); } Assert.IsTrue(pluginGraph.PluginFamilies.Contains<IGateway>()); Modified: trunk/Source/StructureMap.Testing/Configuration/DSL/InstanceExpressionTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Configuration/DSL/InstanceExpressionTester.cs 2007-03-25 02:56:13 UTC (rev 28) +++ trunk/Source/StructureMap.Testing/Configuration/DSL/InstanceExpressionTester.cs 2007-03-26 01:52:39 UTC (rev 29) @@ -21,5 +21,13 @@ PluginGraph pluginGraph = new PluginGraph(); ((IExpression)expression).Configure(pluginGraph); } + + [Test, ExpectedException(typeof(StructureMapException))] + public void BlowUpIfNoPropertyIsFoundForType() + { + InstanceExpression expression = new InstanceExpression(typeof(IWidget)); + expression.UsingConcreteType<AWidget>(); + expression.Child<Rule>(); + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |