From: <fli...@us...> - 2009-10-19 02:59:24
|
Revision: 270 http://structuremap.svn.sourceforge.net/structuremap/?rev=270&view=rev Author: flimflan Date: 2009-10-19 02:59:11 +0000 (Mon, 19 Oct 2009) Log Message: ----------- Experimental support for type scanning which needs to know about all available plugin/concrete types when making a decision. SingleImplementationScanner automatically registers a concrete type if it is the only implementation of an interface. All names/API subject to change... Modified Paths: -------------- trunk/Source/StructureMap/Graph/AssemblyScanner.cs trunk/Source/StructureMap/Graph/ITypeScanner.cs trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap/Util/Cache.cs trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj Added Paths: ----------- trunk/Source/StructureMap/Graph/IHeavyweightTypeScanner.cs trunk/Source/StructureMap/Graph/SingleImplementationScanner.cs trunk/Source/StructureMap.Testing/Graph/SingleImplementationScannerTester.cs Modified: trunk/Source/StructureMap/Graph/AssemblyScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/AssemblyScanner.cs 2009-10-08 16:44:14 UTC (rev 269) +++ trunk/Source/StructureMap/Graph/AssemblyScanner.cs 2009-10-19 02:59:11 UTC (rev 270) @@ -81,6 +81,7 @@ /// <param name="scanner"></param> void With(ITypeScanner scanner); + void With(IHeavyweightTypeScanner heavyweightScanner); /// <summary> /// Adds the DefaultConventionScanner to the scanning operations. I.e., a concrete /// class named "Something" that implements "ISomething" will be automatically @@ -189,6 +190,7 @@ private readonly List<Predicate<Type>> _excludes = new List<Predicate<Type>>(); private readonly List<Predicate<Type>> _includes = new List<Predicate<Type>>(); private readonly List<ITypeScanner> _scanners = new List<ITypeScanner>(); + private readonly List<IHeavyweightTypeScanner> _heavyweightScanners = new List<IHeavyweightTypeScanner>(); public AssemblyScanner() { @@ -204,7 +206,11 @@ internal void ScanForAll(PluginGraph pluginGraph) { + var heavyweightScan = configureHeavyweightScan(); + _assemblies.ForEach(assem => scanTypesInAssembly(assem, pluginGraph)); + + performHeavyweightScan(pluginGraph, heavyweightScan); } private void scanTypesInAssembly(Assembly assembly, PluginGraph graph) @@ -225,6 +231,23 @@ } } + private TypeMapBuilder configureHeavyweightScan() + { + var typeMapBuilder = new TypeMapBuilder(); + if (_heavyweightScanners.Count > 0) + { + With(typeMapBuilder); + } + return typeMapBuilder; + } + + private void performHeavyweightScan(PluginGraph pluginGraph, TypeMapBuilder typeMapBuilder) + { + var typeMaps = typeMapBuilder.GetTypeMaps(); + _heavyweightScanners.ForEach(scanner => scanner.Process(pluginGraph, typeMaps)); + typeMapBuilder.Dispose(); + } + private bool isInTheExcludes(Type type) { if (_excludes.Count == 0) return false; @@ -282,7 +305,14 @@ _scanners.Add(scanner); } + + public void With(IHeavyweightTypeScanner heavyweightScanner) + { + if (_heavyweightScanners.Contains(heavyweightScanner)) return; + _heavyweightScanners.Add(heavyweightScanner); + } + public void WithDefaultConventions() { With<DefaultConventionScanner>(); Added: trunk/Source/StructureMap/Graph/IHeavyweightTypeScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/IHeavyweightTypeScanner.cs (rev 0) +++ trunk/Source/StructureMap/Graph/IHeavyweightTypeScanner.cs 2009-10-19 02:59:11 UTC (rev 270) @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using StructureMap.Util; + +namespace StructureMap.Graph +{ + public interface IHeavyweightTypeScanner + { + void Process(PluginGraph graph, IEnumerable<TypeMap> typeMaps); + } + + + public class TypeMap + { + internal TypeMap(Type pluginType, IList<Type> concreteTypes) + { + PluginType = pluginType; + ConcreteTypes = new ReadOnlyCollection<Type>(concreteTypes); + } + + public IList<Type> ConcreteTypes { get; private set; } + public Type PluginType { get; private set; } + } + + internal class TypeMapBuilder : TypeRules, ITypeScanner, IDisposable + { + private readonly Cache<Type, List<Type>> _implementations = new Cache<Type, List<Type>>(t => new List<Type>()); + + public void Process(Type type, PluginGraph graph) + { + if (!IsConcrete(type) || !Constructor.HasConstructors(type)) return; + var pluginTypes = FindPluginTypes(type); + + foreach (var pluginType in pluginTypes) + { + _implementations[pluginType].Add(type); + } + } + + private IEnumerable<Type> FindPluginTypes(Type type) + { + // lets not worry about abstract base classes for now + return type.GetInterfaces().Where(t => t.IsPublic); + } + + public IEnumerable<TypeMap> GetTypeMaps() + { + return _implementations.Contents().Select(pair => new TypeMap(pair.Key, pair.Value)); + } + + public void Dispose() + { + _implementations.Clear(); + } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/ITypeScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/ITypeScanner.cs 2009-10-08 16:44:14 UTC (rev 269) +++ trunk/Source/StructureMap/Graph/ITypeScanner.cs 2009-10-19 02:59:11 UTC (rev 270) @@ -1,5 +1,4 @@ using System; -using StructureMap; namespace StructureMap.Graph { Added: trunk/Source/StructureMap/Graph/SingleImplementationScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/SingleImplementationScanner.cs (rev 0) +++ trunk/Source/StructureMap/Graph/SingleImplementationScanner.cs 2009-10-19 02:59:11 UTC (rev 270) @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Linq; + +namespace StructureMap.Graph +{ + public class SingleImplementationScanner : TypeRules, IHeavyweightTypeScanner + { + public void Process(PluginGraph graph, IEnumerable<TypeMap> typeMaps) + { + foreach(var map in typeMaps.Where(map => map.ConcreteTypes.Count == 1)) + { + graph.AddType(map.PluginType, map.ConcreteTypes[0]); + } + } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap/StructureMap.csproj =================================================================== --- trunk/Source/StructureMap/StructureMap.csproj 2009-10-08 16:44:14 UTC (rev 269) +++ trunk/Source/StructureMap/StructureMap.csproj 2009-10-19 02:59:11 UTC (rev 270) @@ -395,9 +395,11 @@ <Compile Include="Graph\FamilyAttributeScanner.cs" /> <Compile Include="Graph\FindAllTypesFilter.cs" /> <Compile Include="Graph\FindRegistriesScanner.cs" /> + <Compile Include="Graph\IHeavyweightTypeScanner.cs" /> <Compile Include="Graph\ITypeScanner.cs" /> <Compile Include="Graph\PluggableAttributeScanner.cs" /> <Compile Include="Graph\PluginCache.cs" /> + <Compile Include="Graph\SingleImplementationScanner.cs" /> <Compile Include="IContext.cs" /> <Compile Include="Pipeline\ConditionalInstance.cs" /> <Compile Include="Pipeline\HttpContextLifecycle.cs" /> Modified: trunk/Source/StructureMap/Util/Cache.cs =================================================================== --- trunk/Source/StructureMap/Util/Cache.cs 2009-10-08 16:44:14 UTC (rev 269) +++ trunk/Source/StructureMap/Util/Cache.cs 2009-10-19 02:59:11 UTC (rev 270) @@ -176,6 +176,11 @@ return returnValue; } + public IDictionary<KEY, VALUE> Contents() + { + return _values; + } + public void Remove(KEY key) { if (_values.ContainsKey(key)) Added: trunk/Source/StructureMap.Testing/Graph/SingleImplementationScannerTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/SingleImplementationScannerTester.cs (rev 0) +++ trunk/Source/StructureMap.Testing/Graph/SingleImplementationScannerTester.cs 2009-10-19 02:59:11 UTC (rev 270) @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using NUnit.Framework; +using StructureMap.Graph; +using StructureMap.Util; + +namespace StructureMap.Testing.Graph +{ + [TestFixture] + public class SingleImplementationScannerTester + { + [Test] + public void registers_plugins_that_only_have_a_single_implementation() + { + var container = new Container(registry => + { + registry.Scan(x => + { + x.TheCallingAssembly(); + x.IncludeNamespaceContainingType<SingleImplementationScannerTester>(); + x.With(new SingleImplementationScanner()); + }); + }); + + container.GetInstance<IOnlyHaveASingleConcreteImplementation>() + .ShouldBeOfType<MyNameIsNotConventionallyRelatedToMyInterface>(); + } + + [Test] + public void other() + { + typeof(Type).IsValueType.ShouldBeFalse(); + } + } + + + public interface IOnlyHaveASingleConcreteImplementation + { + + } + public class MyNameIsNotConventionallyRelatedToMyInterface : IOnlyHaveASingleConcreteImplementation + { + + } +} \ No newline at end of file Modified: trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj =================================================================== --- trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2009-10-08 16:44:14 UTC (rev 269) +++ trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2009-10-19 02:59:11 UTC (rev 270) @@ -252,6 +252,7 @@ <Compile Include="Graph\ExceptionHandling\StructureMapExceptionTester.cs"> <SubType>Code</SubType> </Compile> + <Compile Include="Graph\SingleImplementationScannerTester.cs" /> <Compile Include="Graph\TestExplicitArguments.cs" /> <Compile Include="Graph\FillDependenciesTester.cs"> <SubType>Code</SubType> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |