|
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.
|