From: <jer...@us...> - 2009-12-26 18:18:54
|
Revision: 298 http://structuremap.svn.sourceforge.net/structuremap/?rev=298&view=rev Author: jeremydmiller Date: 2009-12-26 18:18:44 +0000 (Sat, 26 Dec 2009) Log Message: ----------- Overhaul of the "single implementation scanning" feature Modified Paths: -------------- trunk/Source/StructureMap/Graph/AssemblyScanner.cs trunk/Source/StructureMap/Graph/IAssemblyScanner.cs trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap/TypeExtensions.cs trunk/Source/StructureMap.Testing/Graph/SingleImplementationScannerTester.cs trunk/Source/StructureMap.Testing/TypeExtensionsTester.cs Added Paths: ----------- trunk/Source/StructureMap/Graph/ImplementationMap.cs Removed Paths: ------------- trunk/Source/StructureMap/Graph/SingleImplementationScanner.cs Modified: trunk/Source/StructureMap/Graph/AssemblyScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/AssemblyScanner.cs 2009-12-26 17:37:30 UTC (rev 297) +++ trunk/Source/StructureMap/Graph/AssemblyScanner.cs 2009-12-26 18:18:44 UTC (rev 298) @@ -41,9 +41,8 @@ private readonly List<Assembly> _assemblies = new List<Assembly>(); private readonly CompositeFilter<Type> _filter = new CompositeFilter<Type>(); - private readonly List<IHeavyweightTypeScanner> _heavyweightScanners = new List<IHeavyweightTypeScanner>(); - private readonly List<ITypeScanner> _scanners = new List<ITypeScanner>(); + private readonly List<Action<PluginGraph>> _postScanningActions = new List<Action<PluginGraph>>(); public AssemblyScanner() { @@ -74,13 +73,6 @@ _scanners.Add(scanner); } - public void With(IHeavyweightTypeScanner heavyweightScanner) - { - if (_heavyweightScanners.Contains(heavyweightScanner)) return; - - _heavyweightScanners.Add(heavyweightScanner); - } - public void WithDefaultConventions() { With<DefaultConventionScanner>(); @@ -182,6 +174,15 @@ With(new GenericConnectionScanner(openGenericType)); } + + private readonly ImplementationMap _implementationMap = new ImplementationMap(); + + public void SingleImplementationsOfInterface() + { + _scanners.Fill(_implementationMap); + _postScanningActions.Add(graph => _implementationMap.RegisterSingleImplementations(graph)); + } + public void AssembliesFromApplicationBaseDirectory() { AssembliesFromApplicationBaseDirectory(a => true); @@ -231,35 +232,15 @@ internal void ScanForAll(PluginGraph pluginGraph) { - //TypeMapBuilder heavyweightScan = configureHeavyweightScan(); - pluginGraph.Types.For(_assemblies, _filter).Each(type => { _scanners.Each(x => x.Process(type, pluginGraph)); }); - //performHeavyweightScan(pluginGraph, heavyweightScan); + _postScanningActions.Each(x => x(pluginGraph)); } - private TypeMapBuilder configureHeavyweightScan() - { - var typeMapBuilder = new TypeMapBuilder(); - if (_heavyweightScanners.Count > 0) - { - With(typeMapBuilder); - } - return typeMapBuilder; - } - - [Obsolete] - private void performHeavyweightScan(PluginGraph pluginGraph, TypeMapBuilder typeMapBuilder) - { - IEnumerable<TypeMap> typeMaps = typeMapBuilder.GetTypeMaps(); - _heavyweightScanners.ForEach(scanner => scanner.Process(pluginGraph, typeMaps)); - typeMapBuilder.Dispose(); - } - public bool Contains(string assemblyName) { foreach (Assembly assembly in _assemblies) Modified: trunk/Source/StructureMap/Graph/IAssemblyScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/IAssemblyScanner.cs 2009-12-26 17:37:30 UTC (rev 297) +++ trunk/Source/StructureMap/Graph/IAssemblyScanner.cs 2009-12-26 18:18:44 UTC (rev 298) @@ -75,8 +75,6 @@ /// <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 @@ -180,5 +178,12 @@ /// </example> /// <param name="openGenericType"></param> void ConnectImplementationsToTypesClosing(Type openGenericType); + + /// <summary> + /// Directs the scanning to automatically register any type that is the single + /// implementation of an interface against that interface. + /// The filters apply + /// </summary> + void SingleImplementationsOfInterface(); } } \ No newline at end of file Added: trunk/Source/StructureMap/Graph/ImplementationMap.cs =================================================================== --- trunk/Source/StructureMap/Graph/ImplementationMap.cs (rev 0) +++ trunk/Source/StructureMap/Graph/ImplementationMap.cs 2009-12-26 18:18:44 UTC (rev 298) @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using StructureMap.TypeRules; +using StructureMap.Util; + +namespace StructureMap.Graph +{ + public class ImplementationMap : ITypeScanner + { + private readonly Cache<Type, List<Type>> _types = new Cache<Type, List<Type>>(t => new List<Type>()); + + public void Register(Type interfaceType, Type concreteType) + { + _types[interfaceType].Add(concreteType); + } + + public void RegisterType(Type type) + { + if (!type.CanBeCreated()) return; + + type.GetInterfaces().Where(i => i.IsVisible).Each(i => Register(i, type)); + } + + public void Process(Type type, PluginGraph graph) + { + RegisterType(type); + } + + public void RegisterSingleImplementations(PluginGraph graph) + { + _types.Each((pluginType, types) => + { + if (types.Count == 1) + { + graph.AddType(pluginType, types[0]); + } + }); + } + } +} \ No newline at end of file Deleted: trunk/Source/StructureMap/Graph/SingleImplementationScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/SingleImplementationScanner.cs 2009-12-26 17:37:30 UTC (rev 297) +++ trunk/Source/StructureMap/Graph/SingleImplementationScanner.cs 2009-12-26 18:18:44 UTC (rev 298) @@ -1,16 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace StructureMap.Graph -{ - public class SingleImplementationScanner : IHeavyweightTypeScanner - { - public void Process(PluginGraph graph, IEnumerable<TypeMap> typeMaps) - { - foreach (TypeMap 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-12-26 17:37:30 UTC (rev 297) +++ trunk/Source/StructureMap/StructureMap.csproj 2009-12-26 18:18:44 UTC (rev 298) @@ -362,11 +362,10 @@ <Compile Include="Graph\FindAllTypesFilter.cs" /> <Compile Include="Graph\FindRegistriesScanner.cs" /> <Compile Include="Graph\IAssemblyScanner.cs" /> - <Compile Include="Graph\IHeavyweightTypeScanner.cs" /> + <Compile Include="Graph\ImplementationMap.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\Arguments.cs" /> <Compile Include="Pipeline\ArrayCoercion.cs" /> Modified: trunk/Source/StructureMap/TypeExtensions.cs =================================================================== --- trunk/Source/StructureMap/TypeExtensions.cs 2009-12-26 17:37:30 UTC (rev 297) +++ trunk/Source/StructureMap/TypeExtensions.cs 2009-12-26 18:18:44 UTC (rev 298) @@ -7,6 +7,13 @@ { public static class BasicExtensions { + public static void Fill<T>(this IList<T> list, T value) + { + if (list.Contains(value)) return; + list.Add(value); + } + + public static void TryGet<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Action<TValue> action) { @@ -139,6 +146,19 @@ return type.FullName; } + public static bool CanBeCreated(this Type type) + { + return type.IsConcrete() && Constructor.HasConstructors(type); + } + + public static IEnumerable<Type> AllInterfaces(this Type type) + { + foreach (var @interface in type.GetInterfaces()) + { + yield return @interface; + } + } + /// <summary> /// Determines if the pluggedType can be upcast to the pluginType /// </summary> Modified: trunk/Source/StructureMap.Testing/Graph/SingleImplementationScannerTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/SingleImplementationScannerTester.cs 2009-12-26 17:37:30 UTC (rev 297) +++ trunk/Source/StructureMap.Testing/Graph/SingleImplementationScannerTester.cs 2009-12-26 18:18:44 UTC (rev 298) @@ -13,7 +13,7 @@ typeof (Type).IsValueType.ShouldBeFalse(); } - [Test, Ignore("Come back to this")] + [Test] public void registers_plugins_that_only_have_a_single_implementation() { var container = new Container(registry => @@ -22,7 +22,7 @@ { x.TheCallingAssembly(); x.IncludeNamespaceContainingType<SingleImplementationScannerTester>(); - x.With(new SingleImplementationScanner()); + x.SingleImplementationsOfInterface(); }); }); Modified: trunk/Source/StructureMap.Testing/TypeExtensionsTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/TypeExtensionsTester.cs 2009-12-26 17:37:30 UTC (rev 297) +++ trunk/Source/StructureMap.Testing/TypeExtensionsTester.cs 2009-12-26 18:18:44 UTC (rev 298) @@ -102,5 +102,22 @@ Assert.IsTrue(typeof (string).IsString()); Assert.IsFalse(typeof (int).IsString()); } + + [Test] + public void get_all_interfaces() + { + typeof(C3).AllInterfaces().ShouldHaveTheSameElementsAs(typeof(I1), typeof(I2), typeof(I3)); + typeof(C2).AllInterfaces().ShouldHaveTheSameElementsAs(typeof(I1), typeof(I2)); + typeof(C1).AllInterfaces().ShouldHaveTheSameElementsAs(typeof(I1)); + } } + + + public interface I1{} + public interface I2{} + public interface I3{} + + public class C1 : I1{} + public class C2 : C1, I2{} + public class C3 : C2, I3{} } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |