From: <jer...@us...> - 2009-12-28 04:07:29
|
Revision: 309 http://structuremap.svn.sourceforge.net/structuremap/?rev=309&view=rev Author: jeremydmiller Date: 2009-12-28 04:07:20 +0000 (Mon, 28 Dec 2009) Log Message: ----------- Finished the work on the new "Model" subsystem Modified Paths: -------------- trunk/Source/StructureMap/Container.cs trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs trunk/Source/StructureMap/Graph/PluginFamily.cs trunk/Source/StructureMap/Pipeline/Profile.cs trunk/Source/StructureMap/Pipeline/ProfileManager.cs trunk/Source/StructureMap/PipelineGraph.cs trunk/Source/StructureMap/Query/EmptyConfiguration.cs trunk/Source/StructureMap/Query/GenericFamilyConfiguration.cs trunk/Source/StructureMap/Query/IModel.cs trunk/Source/StructureMap/Query/IPluginTypeConfiguration.cs trunk/Source/StructureMap/Query/InstanceFactoryTypeConfiguration.cs trunk/Source/StructureMap/Query/Model.cs trunk/Source/StructureMap/TypeExtensions.cs trunk/Source/StructureMap.Testing/Graph/PluginFamilyTester.cs trunk/Source/StructureMap.Testing/Query/ModelIntegrationTester.cs Modified: trunk/Source/StructureMap/Container.cs =================================================================== --- trunk/Source/StructureMap/Container.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Container.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -64,7 +64,13 @@ /// <summary> /// Provides queryable access to the configured PluginType's and Instances of this Container /// </summary> - public IModel Model { get { return new Model(_pipelineGraph.GetPluginTypes(this)); } } + public IModel Model + { + get + { + return new Model(_pipelineGraph, this); + } + } /// <summary> /// Creates or finds the named instance of T Modified: trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs =================================================================== --- trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -160,5 +160,10 @@ { _families.Clear(); } + + public void Remove(Type pluginType) + { + _families.Remove(pluginType); + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/PluginFamily.cs =================================================================== --- trunk/Source/StructureMap/Graph/PluginFamily.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Graph/PluginFamily.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -361,5 +361,12 @@ } } + + public void RemoveAll() + { + _instances.Clear(); + _mementoList.Clear(); + _defaultKey = null; + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Pipeline/Profile.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/Profile.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Pipeline/Profile.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -105,9 +105,9 @@ } - public void Remove<T>() + public void Remove(Type pluginType) { - _instances.Remove(typeof (T)); + _instances.Remove(pluginType); } public void Clear() Modified: trunk/Source/StructureMap/Pipeline/ProfileManager.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/ProfileManager.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Pipeline/ProfileManager.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -216,13 +216,9 @@ return clone; } - public void EjectAllInstancesOf<T>() + public void EjectAllInstancesOf(Type pluginType) { - _currentProfile.Remove<T>(); - foreach (var pair in _profiles) - { - pair.Value.Remove<T>(); - } + profiles.Each(x => x.Remove(pluginType)); } public void RemoveInstance(Type pluginType, Instance instance) Modified: trunk/Source/StructureMap/PipelineGraph.cs =================================================================== --- trunk/Source/StructureMap/PipelineGraph.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/PipelineGraph.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -188,11 +188,29 @@ public void EjectAllInstancesOf<T>() { - ForType(typeof (T)).EjectAllInstances(); - _profileManager.EjectAllInstancesOf<T>(); + EjectAllInstancesOf(typeof(T)); } + public void EjectAllInstancesOf(Type pluginType) + { + ForType(pluginType).EjectAllInstances(); + _profileManager.EjectAllInstancesOf(pluginType); + } + public void Remove(Func<Type, bool> filter) + { + _genericsGraph.Families.Where(x => filter(x.PluginType)).ToArray().Each(x => Remove(x.PluginType)); + _factories.Values.Where(x => filter(x.PluginType)).ToArray().Each(x => Remove(x.PluginType)); + } + + public void Remove(Type pluginType) + { + EjectAllInstancesOf(pluginType); + _factories.Remove(pluginType); + _genericsGraph.Remove(pluginType); + } + + public List<Instance> GetAllInstances() { return _factories.Values.SelectMany(x => x.AllInstances).ToList(); @@ -232,5 +250,8 @@ ForType(pluginType).RemoveInstance(instance); _profileManager.RemoveInstance(pluginType, instance); } + + + } } \ No newline at end of file Modified: trunk/Source/StructureMap/Query/EmptyConfiguration.cs =================================================================== --- trunk/Source/StructureMap/Query/EmptyConfiguration.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Query/EmptyConfiguration.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -44,5 +44,8 @@ { } + public void EjectAndRemoveAll() + { + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Query/GenericFamilyConfiguration.cs =================================================================== --- trunk/Source/StructureMap/Query/GenericFamilyConfiguration.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Query/GenericFamilyConfiguration.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -70,6 +70,9 @@ _family.RemoveInstance(instance.Instance); } - + public void EjectAndRemoveAll() + { + _family.RemoveAll(); + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Query/IModel.cs =================================================================== --- trunk/Source/StructureMap/Query/IModel.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Query/IModel.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -90,5 +90,32 @@ /// <param name="type"></param> /// <returns></returns> IPluginTypeConfiguration For(Type type); + + /// <summary> + /// Eject all objects, configuration, and Plugin Types matching this filter + /// </summary> + /// <param name="filter"></param> + void EjectAndRemoveTypes(Func<Type, bool> filter); + + /// <summary> + /// Eject all objects and configuration for any Plugin Type that matches this filter + /// </summary> + /// <param name="filter"></param> + void EjectAndRemovePluginTypes(Func<Type, bool> filter); + + /// <summary> + /// Eject all objects and Instance configuration for this PluginType + /// </summary> + /// <param name="pluginType"></param> + void EjectAndRemove(Type pluginType); + + + /// <summary> + /// Get each and every configured instance that could possibly + /// be cast to T + /// </summary> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + IEnumerable<T> GetAllPossible<T>() where T : class; } } \ No newline at end of file Modified: trunk/Source/StructureMap/Query/IPluginTypeConfiguration.cs =================================================================== --- trunk/Source/StructureMap/Query/IPluginTypeConfiguration.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Query/IPluginTypeConfiguration.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -38,6 +38,11 @@ /// <param name="instance"></param> void EjectAndRemove(InstanceRef instance); + /// <summary> + /// Eject all instances of this PluginType from the current container, + /// but leaves the lifecycle behavior + /// </summary> + void EjectAndRemoveAll(); } public static class PluginTypeConfigurationExtensions Modified: trunk/Source/StructureMap/Query/InstanceFactoryTypeConfiguration.cs =================================================================== --- trunk/Source/StructureMap/Query/InstanceFactoryTypeConfiguration.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Query/InstanceFactoryTypeConfiguration.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -80,7 +80,12 @@ _graph.Remove(_pluginType, instance.Instance); } - + public void EjectAndRemoveAll() + { + _graph.EjectAllInstancesOf(_pluginType); + } + + private InstanceRef toRef(Instance instance) { if (instance == null) return null; Modified: trunk/Source/StructureMap/Query/Model.cs =================================================================== --- trunk/Source/StructureMap/Query/Model.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/Query/Model.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -1,16 +1,19 @@ using System; using System.Collections.Generic; using System.Linq; +using StructureMap.TypeRules; namespace StructureMap.Query { public class Model : IModel { - private readonly IEnumerable<IPluginTypeConfiguration> _pluginTypes; + private PipelineGraph _graph; + private IContainer _container; - internal Model(IEnumerable<IPluginTypeConfiguration> pluginTypes) + internal Model(PipelineGraph graph, IContainer container) { - _pluginTypes = pluginTypes; + _graph = graph; + _container = container; } #region IModel Members @@ -35,8 +38,16 @@ return findForFamily(pluginType, f => f.Default == null ? null : f.Default.ConcreteType); } - public IEnumerable<IPluginTypeConfiguration> PluginTypes { get { return _pluginTypes; } } + private IEnumerable<IPluginTypeConfiguration> pluginTypes + { + get + { + return _graph.GetPluginTypes(_container); + } + } + public IEnumerable<IPluginTypeConfiguration> PluginTypes { get { return pluginTypes; } } + /// <summary> /// Retrieves the configuration for the given type /// </summary> @@ -54,9 +65,58 @@ /// <returns></returns> public IPluginTypeConfiguration For(Type type) { - return _pluginTypes.FirstOrDefault(x => x.PluginType == type) ?? new EmptyConfiguration(type); + return pluginTypes.FirstOrDefault(x => x.PluginType == type) ?? new EmptyConfiguration(type); } + /// <summary> + /// Eject all objects, configuration, and Plugin Types matching this filter + /// </summary> + /// <param name="filter"></param> + public void EjectAndRemoveTypes(Func<Type, bool> filter) + { + // first pass hits plugin types + EjectAndRemovePluginTypes(filter); + + // second pass to hit instances + pluginTypes.Each(x => + { + x.EjectAndRemove(i => filter(i.ConcreteType)); + }); + } + + /// <summary> + /// Eject all objects and configuration for any Plugin Type that matches this filter + /// </summary> + /// <param name="filter"></param> + public void EjectAndRemovePluginTypes(Func<Type, bool> filter) + { + _graph.Remove(filter); + } + + /// <summary> + /// Eject all objects and Instance configuration for this PluginType + /// </summary> + /// <param name="pluginType"></param> + public void EjectAndRemove(Type pluginType) + { + _graph.Remove(pluginType); + } + + /// <summary> + /// Get each and every configured instance that could possibly + /// be cast to T + /// </summary> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + public IEnumerable<T> GetAllPossible<T>() where T : class + { + Type targetType = typeof (T); + return AllInstances + .Where(x => x.ConcreteType.CanBeCastTo(targetType)) + .Select(x => x.Get<T>()) + .Where(x => x != null); + } + public IEnumerable<InstanceRef> InstancesOf(Type pluginType) { return findForFamily(pluginType, x => x.Instances, new InstanceRef[0]); Modified: trunk/Source/StructureMap/TypeExtensions.cs =================================================================== --- trunk/Source/StructureMap/TypeExtensions.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap/TypeExtensions.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -173,6 +173,8 @@ /// <returns></returns> public static bool CanBeCastTo(this Type pluggedType, Type pluginType) { + if (pluggedType == null) return false; + if (pluggedType.IsInterface || pluggedType.IsAbstract) { return false; Modified: trunk/Source/StructureMap.Testing/Graph/PluginFamilyTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/PluginFamilyTester.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap.Testing/Graph/PluginFamilyTester.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -208,6 +208,24 @@ } [Test] + public void remove_all_clears_the_defaul_and_removes_all_plugins_instances() + { + var family = new PluginFamily(typeof(IServiceProvider)); + var instance = new SmartInstance<DataSet>(); + + family.SetDefault(instance); + + family.AddInstance(new NullInstance()); + family.AddType(typeof(DataSet)); + + family.RemoveAll(); + + family.DefaultInstanceKey.ShouldBeNull(); + + family.InstanceCount.ShouldEqual(0); + } + + [Test] public void set_the_scope_to_session() { var family = new PluginFamily(typeof (IServiceProvider)); Modified: trunk/Source/StructureMap.Testing/Query/ModelIntegrationTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Query/ModelIntegrationTester.cs 2009-12-28 02:57:22 UTC (rev 308) +++ trunk/Source/StructureMap.Testing/Query/ModelIntegrationTester.cs 2009-12-28 04:07:20 UTC (rev 309) @@ -32,6 +32,10 @@ }); x.For<IEngine>().Use<PushrodEngine>(); + + x.For<Startable1>().Singleton().Use<Startable1>(); + x.For<Startable2>().Use<Startable2>(); + x.For<Startable3>().Use<Startable3>(); }); } @@ -40,10 +44,63 @@ private Container container; [Test] + public void remove_types_based_on_a_filter() + { + container.GetAllInstances<Rule>().Any(x => x is ARule).ShouldBeTrue(); + container.Model.HasImplementationsFor<IWidget>().ShouldBeTrue(); + + container.Model.EjectAndRemoveTypes(t => t == typeof(IWidget) || t == typeof(ARule)); + + container.GetAllInstances<Rule>().Any(x => x is ARule).ShouldBeFalse(); + container.Model.HasImplementationsFor<IWidget>().ShouldBeFalse(); + } + + [Test] + public void remove_an_entire_closed_type() + { + container.Model.EjectAndRemove(typeof(Rule)); + container.Model.HasImplementationsFor<Rule>().ShouldBeFalse(); + + container.TryGetInstance<Rule>().ShouldBeNull(); + container.GetAllInstances<Rule>().Count.ShouldEqual(0); + + } + + [Test] + public void remove_an_entire_closed_type_with_the_filter() + { + container.Model.EjectAndRemovePluginTypes(t => t == typeof(Rule) || t == typeof(IWidget)); + + container.Model.HasImplementationsFor<IWidget>().ShouldBeFalse(); + container.Model.HasImplementationsFor<Rule>().ShouldBeFalse(); + container.Model.HasImplementationsFor<IEngine>().ShouldBeTrue(); + } + + [Test] + public void remove_an_open_type() + { + container.Model.EjectAndRemove(typeof(IService<>)); + + container.Model.HasImplementationsFor(typeof (IService<>)); + + container.TryGetInstance<IService<string>>().ShouldBeNull(); + } + + [Test] + public void remove_an_open_type_with_a_filter() + { + container.Model.EjectAndRemovePluginTypes(t => t == typeof(IService<>)); + + container.Model.HasImplementationsFor(typeof(IService<>)); + + container.TryGetInstance<IService<string>>().ShouldBeNull(); + } + + [Test] public void can_iterate_through_families_including_both_generics_and_normal() { // +1 for "IContainer" itself - container.Model.PluginTypes.Count().ShouldEqual(5); + container.Model.PluginTypes.Count().ShouldEqual(8); container.Model.PluginTypes.Each(x => Debug.WriteLine(x.PluginType.FullName)); } @@ -82,7 +139,7 @@ [Test] public void get_all_instances_from_the_top() { - container.Model.AllInstances.Count().ShouldEqual(8); + container.Model.AllInstances.Count().ShouldEqual(11); } [Test] @@ -105,5 +162,42 @@ { container.Model.For<ISomething>().HasImplementations().ShouldBeFalse(); } + + [Test] + public void get_all_possibles() + { + // Startable1 is a singleton + + var startable1 = container.GetInstance<Startable1>(); + startable1.WasStarted.ShouldBeFalse(); + + container.Model.GetAllPossible<IStartable>() + .ToArray() + .Each(x => x.Start()) + .Each(x => x.WasStarted.ShouldBeTrue()); + + startable1.WasStarted.ShouldBeTrue(); + } } + + + public interface IStartable + { + void Start(); + bool WasStarted { get; } + } + + public class Startable : IStartable + { + public void Start() + { + WasStarted = true; + } + + public bool WasStarted { get; private set; } + } + + public class Startable1 : Startable{} + public class Startable2 : Startable{} + public class Startable3 : Startable{} } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |