From: <jer...@us...> - 2009-12-26 17:37:37
|
Revision: 297 http://structuremap.svn.sourceforge.net/structuremap/?rev=297&view=rev Author: jeremydmiller Date: 2009-12-26 17:37:30 +0000 (Sat, 26 Dec 2009) Log Message: ----------- Redo of the assembly scanning. Mild optimization Modified Paths: -------------- trunk/Source/StructureMap/Graph/AssemblyScanner.cs trunk/Source/StructureMap/Graph/IHeavyweightTypeScanner.cs trunk/Source/StructureMap/Graph/PluginGraph.cs trunk/Source/StructureMap/StructureMap.csproj Added Paths: ----------- trunk/Source/StructureMap/Graph/CompositeFilter.cs trunk/Source/StructureMap/Graph/CompositePredicate.cs trunk/Source/StructureMap/Graph/IAssemblyScanner.cs Modified: trunk/Source/StructureMap/Graph/AssemblyScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/AssemblyScanner.cs 2009-12-26 05:45:56 UTC (rev 296) +++ trunk/Source/StructureMap/Graph/AssemblyScanner.cs 2009-12-26 17:37:30 UTC (rev 297) @@ -5,194 +5,44 @@ using System.Linq; using System.Reflection; using StructureMap.TypeRules; +using StructureMap.Util; namespace StructureMap.Graph { - public interface IAssemblyScanner + public class TypePool { - #region Designating Assemblies + private readonly Cache<Assembly, Type[]> _types = new Cache<Assembly, Type[]>(); - /// <summary> - /// Add an Assembly to the scanning operation - /// </summary> - /// <param name="assembly"></param> - void Assembly(Assembly assembly); + public TypePool(PluginGraph graph) + { + _types.OnMissing = assembly => + { + try + { + return assembly.GetExportedTypes(); + } + catch (Exception ex) + { + graph.Log.RegisterError(170, ex, assembly.FullName); + return new Type[0]; + } + }; + } - /// <summary> - /// Add an Assembly by name to the scanning operation - /// </summary> - /// <param name="assemblyName"></param> - void Assembly(string assemblyName); - - /// <summary> - /// Add the currently executing Assembly to the scanning operation - /// </summary> - void TheCallingAssembly(); - - /// <summary> - /// Add the Assembly that contains type T to the scanning operation - /// </summary> - /// <typeparam name="T"></typeparam> - void AssemblyContainingType<T>(); - - /// <summary> - /// Add the Assembly that contains type to the scanning operation - /// </summary> - /// <param name="type"></param> - void AssemblyContainingType(Type type); - - /// <summary> - /// Sweep the designated path and add any Assembly's found in this folder to the - /// scanning operation - /// </summary> - /// <param name="path"></param> - void AssembliesFromPath(string path); - - /// <summary> - /// Sweep the designated path and add any Assembly's found in this folder to the - /// scanning operation. The assemblyFilter can be used to filter or limit the - /// Assembly's that are picked up. - /// </summary> - /// <param name="path"></param> - /// <param name="assemblyFilter"></param> - void AssembliesFromPath(string path, Predicate<Assembly> assemblyFilter); - - /// <summary> - /// Sweep the application base directory of current app domain and add any Assembly's - /// found to the scanning operation. - /// </summary> - void AssembliesFromApplicationBaseDirectory(); - - /// <summary> - /// Sweep the application base directory of current app domain and add any Assembly's - /// found to the scanning operation. The assemblyFilter can be used to filter or limit the - /// Assembly's that are picked up. - /// </summary> - void AssembliesFromApplicationBaseDirectory(Predicate<Assembly> assemblyFilter); - - #endregion - - #region Adding TypeScanners - - /// <summary> - /// Adds an ITypeScanner object to the scanning operation - /// </summary> - /// <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 - /// added to PluginType "ISomething" - /// </summary> - void WithDefaultConventions(); - - /// <summary> - /// Creates and adds a new ITypeScanner of type T to this scanning operation - /// </summary> - /// <typeparam name="T"></typeparam> - void With<T>() where T : ITypeScanner, new(); - - #endregion - - #region Other options - - /// <summary> - /// Directs the scanning operation to automatically detect and include any Registry - /// classes found in the Assembly's being scanned - /// </summary> - void LookForRegistries(); - - /// <summary> - /// Add all concrete types of the Plugin Type as Instances of Plugin Type - /// </summary> - /// <typeparam name="PLUGINTYPE"></typeparam> - FindAllTypesFilter AddAllTypesOf<PLUGINTYPE>(); - - /// <summary> - /// Add all concrete types of the Plugin Type as Instances of Plugin Type - /// </summary> - /// <param name="pluginType"></param> - FindAllTypesFilter AddAllTypesOf(Type pluginType); - - /// <summary> - /// Makes this scanning operation ignore all [PluginFamily] and [Pluggable] attributes - /// </summary> - void IgnoreStructureMapAttributes(); - - #endregion - - #region Filtering types - - /// <summary> - /// Exclude types that match the Predicate from being scanned - /// </summary> - /// <param name="exclude"></param> - void Exclude(Predicate<Type> exclude); - - /// <summary> - /// Exclude all types in this nameSpace or its children from the scanning operation - /// </summary> - /// <param name="nameSpace"></param> - void ExcludeNamespace(string nameSpace); - - /// <summary> - /// Exclude all types in this nameSpace or its children from the scanning operation - /// </summary> - /// <typeparam name="T"></typeparam> - void ExcludeNamespaceContainingType<T>(); - - /// <summary> - /// Only include types matching the Predicate in the scanning operation. You can - /// use multiple Include() calls in a single scanning operation - /// </summary> - /// <param name="predicate"></param> - void Include(Predicate<Type> predicate); - - /// <summary> - /// Only include types from this nameSpace or its children in the scanning operation. You can - /// use multiple Include() calls in a single scanning operation - /// </summary> - /// <param name="nameSpace"></param> - void IncludeNamespace(string nameSpace); - - /// <summary> - /// Only include types from this nameSpace or its children in the scanning operation. You can - /// use multiple Include() calls in a single scanning operation - /// </summary> - /// <typeparam name="T"></typeparam> - void IncludeNamespaceContainingType<T>(); - - /// <summary> - /// Exclude this specific type from the scanning operation - /// </summary> - /// <typeparam name="T"></typeparam> - void ExcludeType<T>(); - - // ... Other methods - - #endregion - - // ... Other methods - - /// <summary> - /// Scans for PluginType's and Concrete Types that close the given open generic type - /// </summary> - /// <example> - /// - /// </example> - /// <param name="openGenericType"></param> - void ConnectImplementationsToTypesClosing(Type openGenericType); + public IEnumerable<Type> For(IEnumerable<Assembly> assemblies, CompositeFilter<Type> filter) + { + return assemblies.SelectMany(x => _types[x].Where(filter.Matches)); + } } + public class AssemblyScanner : IAssemblyScanner { private readonly List<Assembly> _assemblies = new List<Assembly>(); - private readonly List<Predicate<Type>> _excludes = new List<Predicate<Type>>(); + private readonly CompositeFilter<Type> _filter = new CompositeFilter<Type>(); + private readonly List<IHeavyweightTypeScanner> _heavyweightScanners = new List<IHeavyweightTypeScanner>(); - private readonly List<Predicate<Type>> _includes = new List<Predicate<Type>>(); + private readonly List<ITypeScanner> _scanners = new List<ITypeScanner>(); public AssemblyScanner() @@ -292,9 +142,9 @@ } - public void Exclude(Predicate<Type> exclude) + public void Exclude(Func<Type, bool> exclude) { - _excludes.Add(exclude); + _filter.Excludes += exclude; } public void ExcludeNamespace(string nameSpace) @@ -307,9 +157,9 @@ ExcludeNamespace(typeof (T).Namespace); } - public void Include(Predicate<Type> predicate) + public void Include(Func<Type, bool> predicate) { - _includes.Add(predicate); + _filter.Includes += predicate; } public void IncludeNamespace(string nameSpace) @@ -381,31 +231,17 @@ internal void ScanForAll(PluginGraph pluginGraph) { - TypeMapBuilder heavyweightScan = configureHeavyweightScan(); + //TypeMapBuilder heavyweightScan = configureHeavyweightScan(); - _assemblies.ForEach(assem => scanTypesInAssembly(assem, pluginGraph)); - - performHeavyweightScan(pluginGraph, heavyweightScan); - } - - private void scanTypesInAssembly(Assembly assembly, PluginGraph graph) - { - try + pluginGraph.Types.For(_assemblies, _filter).Each(type => { - foreach (Type type in assembly.GetExportedTypes()) - { - if (!isInTheIncludes(type)) continue; - if (isInTheExcludes(type)) continue; + _scanners.Each(x => x.Process(type, pluginGraph)); + }); - _scanners.ForEach(scanner => scanner.Process(type, graph)); - } - } - catch (Exception ex) - { - graph.Log.RegisterError(170, ex, assembly.FullName); - } + //performHeavyweightScan(pluginGraph, heavyweightScan); } + private TypeMapBuilder configureHeavyweightScan() { var typeMapBuilder = new TypeMapBuilder(); @@ -416,6 +252,7 @@ return typeMapBuilder; } + [Obsolete] private void performHeavyweightScan(PluginGraph pluginGraph, TypeMapBuilder typeMapBuilder) { IEnumerable<TypeMap> typeMaps = typeMapBuilder.GetTypeMaps(); @@ -423,31 +260,6 @@ typeMapBuilder.Dispose(); } - private bool isInTheExcludes(Type type) - { - if (_excludes.Count == 0) return false; - - foreach (var exclude in _excludes) - { - if (exclude(type)) return true; - } - - return false; - } - - private bool isInTheIncludes(Type type) - { - if (_includes.Count == 0) return true; - - - foreach (var include in _includes) - { - if (include(type)) return true; - } - - return false; - } - public bool Contains(string assemblyName) { foreach (Assembly assembly in _assemblies) Added: trunk/Source/StructureMap/Graph/CompositeFilter.cs =================================================================== --- trunk/Source/StructureMap/Graph/CompositeFilter.cs (rev 0) +++ trunk/Source/StructureMap/Graph/CompositeFilter.cs 2009-12-26 17:37:30 UTC (rev 297) @@ -0,0 +1,16 @@ +namespace StructureMap.Graph +{ + public class CompositeFilter<T> + { + private readonly CompositePredicate<T> _excludes = new CompositePredicate<T>(); + private readonly CompositePredicate<T> _includes = new CompositePredicate<T>(); + + public CompositePredicate<T> Includes { get { return _includes; } set { } } + public CompositePredicate<T> Excludes { get { return _excludes; } set { } } + + public bool Matches(T target) + { + return Includes.MatchesAny(target) && Excludes.DoesNotMatcheAny(target); + } + } +} \ No newline at end of file Added: trunk/Source/StructureMap/Graph/CompositePredicate.cs =================================================================== --- trunk/Source/StructureMap/Graph/CompositePredicate.cs (rev 0) +++ trunk/Source/StructureMap/Graph/CompositePredicate.cs 2009-12-26 17:37:30 UTC (rev 297) @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace StructureMap.Graph +{ + public class CompositePredicate<T> + { + private readonly List<Func<T, bool>> _list = new List<Func<T, bool>>(); + private Func<T, bool> _matchesAll = x => true; + private Func<T, bool> _matchesAny = x => true; + private Func<T, bool> _matchesNone = x => false; + + public void Add(Func<T, bool> filter) + { + _matchesAll = x => _list.All(predicate => predicate(x)); + _matchesAny = x => _list.Any(predicate => predicate(x)); + _matchesNone = x => !MatchesAny(x); + + _list.Add(filter); + } + + public static CompositePredicate<T> operator +(CompositePredicate<T> invokes, Func<T, bool> filter) + { + invokes.Add(filter); + return invokes; + } + + public bool MatchesAll(T target) + { + return _matchesAll(target); + } + + public bool MatchesAny(T target) + { + return _matchesAny(target); + } + + public bool MatchesNone(T target) + { + return _matchesNone(target); + } + + public bool DoesNotMatcheAny(T target) + { + return _list.Count == 0 ? true : !MatchesAny(target); + } + } +} \ No newline at end of file Added: trunk/Source/StructureMap/Graph/IAssemblyScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/IAssemblyScanner.cs (rev 0) +++ trunk/Source/StructureMap/Graph/IAssemblyScanner.cs 2009-12-26 17:37:30 UTC (rev 297) @@ -0,0 +1,184 @@ +using System; +using System.Reflection; + +namespace StructureMap.Graph +{ + public interface IAssemblyScanner + { + #region Designating Assemblies + + /// <summary> + /// Add an Assembly to the scanning operation + /// </summary> + /// <param name="assembly"></param> + void Assembly(Assembly assembly); + + /// <summary> + /// Add an Assembly by name to the scanning operation + /// </summary> + /// <param name="assemblyName"></param> + void Assembly(string assemblyName); + + /// <summary> + /// Add the currently executing Assembly to the scanning operation + /// </summary> + void TheCallingAssembly(); + + /// <summary> + /// Add the Assembly that contains type T to the scanning operation + /// </summary> + /// <typeparam name="T"></typeparam> + void AssemblyContainingType<T>(); + + /// <summary> + /// Add the Assembly that contains type to the scanning operation + /// </summary> + /// <param name="type"></param> + void AssemblyContainingType(Type type); + + /// <summary> + /// Sweep the designated path and add any Assembly's found in this folder to the + /// scanning operation + /// </summary> + /// <param name="path"></param> + void AssembliesFromPath(string path); + + /// <summary> + /// Sweep the designated path and add any Assembly's found in this folder to the + /// scanning operation. The assemblyFilter can be used to filter or limit the + /// Assembly's that are picked up. + /// </summary> + /// <param name="path"></param> + /// <param name="assemblyFilter"></param> + void AssembliesFromPath(string path, Predicate<Assembly> assemblyFilter); + + /// <summary> + /// Sweep the application base directory of current app domain and add any Assembly's + /// found to the scanning operation. + /// </summary> + void AssembliesFromApplicationBaseDirectory(); + + /// <summary> + /// Sweep the application base directory of current app domain and add any Assembly's + /// found to the scanning operation. The assemblyFilter can be used to filter or limit the + /// Assembly's that are picked up. + /// </summary> + void AssembliesFromApplicationBaseDirectory(Predicate<Assembly> assemblyFilter); + + #endregion + + #region Adding TypeScanners + + /// <summary> + /// Adds an ITypeScanner object to the scanning operation + /// </summary> + /// <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 + /// added to PluginType "ISomething" + /// </summary> + void WithDefaultConventions(); + + /// <summary> + /// Creates and adds a new ITypeScanner of type T to this scanning operation + /// </summary> + /// <typeparam name="T"></typeparam> + void With<T>() where T : ITypeScanner, new(); + + #endregion + + #region Other options + + /// <summary> + /// Directs the scanning operation to automatically detect and include any Registry + /// classes found in the Assembly's being scanned + /// </summary> + void LookForRegistries(); + + /// <summary> + /// Add all concrete types of the Plugin Type as Instances of Plugin Type + /// </summary> + /// <typeparam name="PLUGINTYPE"></typeparam> + FindAllTypesFilter AddAllTypesOf<PLUGINTYPE>(); + + /// <summary> + /// Add all concrete types of the Plugin Type as Instances of Plugin Type + /// </summary> + /// <param name="pluginType"></param> + FindAllTypesFilter AddAllTypesOf(Type pluginType); + + /// <summary> + /// Makes this scanning operation ignore all [PluginFamily] and [Pluggable] attributes + /// </summary> + void IgnoreStructureMapAttributes(); + + #endregion + + #region Filtering types + + /// <summary> + /// Exclude types that match the Predicate from being scanned + /// </summary> + /// <param name="exclude"></param> + void Exclude(Func<Type, bool> exclude); + + /// <summary> + /// Exclude all types in this nameSpace or its children from the scanning operation + /// </summary> + /// <param name="nameSpace"></param> + void ExcludeNamespace(string nameSpace); + + /// <summary> + /// Exclude all types in this nameSpace or its children from the scanning operation + /// </summary> + /// <typeparam name="T"></typeparam> + void ExcludeNamespaceContainingType<T>(); + + /// <summary> + /// Only include types matching the Predicate in the scanning operation. You can + /// use multiple Include() calls in a single scanning operation + /// </summary> + /// <param name="predicate"></param> + void Include(Func<Type, bool> predicate); + + /// <summary> + /// Only include types from this nameSpace or its children in the scanning operation. You can + /// use multiple Include() calls in a single scanning operation + /// </summary> + /// <param name="nameSpace"></param> + void IncludeNamespace(string nameSpace); + + /// <summary> + /// Only include types from this nameSpace or its children in the scanning operation. You can + /// use multiple Include() calls in a single scanning operation + /// </summary> + /// <typeparam name="T"></typeparam> + void IncludeNamespaceContainingType<T>(); + + /// <summary> + /// Exclude this specific type from the scanning operation + /// </summary> + /// <typeparam name="T"></typeparam> + void ExcludeType<T>(); + + // ... Other methods + + #endregion + + // ... Other methods + + /// <summary> + /// Scans for PluginType's and Concrete Types that close the given open generic type + /// </summary> + /// <example> + /// + /// </example> + /// <param name="openGenericType"></param> + void ConnectImplementationsToTypesClosing(Type openGenericType); + } +} \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/IHeavyweightTypeScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/IHeavyweightTypeScanner.cs 2009-12-26 05:45:56 UTC (rev 296) +++ trunk/Source/StructureMap/Graph/IHeavyweightTypeScanner.cs 2009-12-26 17:37:30 UTC (rev 297) @@ -7,6 +7,7 @@ namespace StructureMap.Graph { + [Obsolete] public interface IHeavyweightTypeScanner { void Process(PluginGraph graph, IEnumerable<TypeMap> typeMaps); Modified: trunk/Source/StructureMap/Graph/PluginGraph.cs =================================================================== --- trunk/Source/StructureMap/Graph/PluginGraph.cs 2009-12-26 05:45:56 UTC (rev 296) +++ trunk/Source/StructureMap/Graph/PluginGraph.cs 2009-12-26 17:37:30 UTC (rev 297) @@ -33,6 +33,33 @@ void AddType(Type pluggedType); } + + public class WeakReference<T> + { + private readonly Func<T> _builder; + private readonly WeakReference _reference; + + public WeakReference(Func<T> builder) + { + _builder = builder; + _reference = new WeakReference(_builder()); + } + + public T Value + { + get + { + if (!_reference.IsAlive) + { + _reference.Target = _builder(); + } + + return (T)_reference.Target; + } + } + } + + /// <summary> /// Models the runtime configuration of a StructureMap Container /// </summary> @@ -47,17 +74,21 @@ private readonly List<AssemblyScanner> _scanners = new List<AssemblyScanner>(); private GraphLog _log = new GraphLog(); private bool _sealed; + private readonly WeakReference<TypePool> _types; public PluginGraph() { _pluginFamilies = new PluginFamilyCollection(this); + _types = new WeakReference<TypePool>(() => new TypePool(this)); } - public PluginGraph(AssemblyScanner assemblies) + public TypePool Types { - _pluginFamilies = new PluginFamilyCollection(this); - _scanners.Add(assemblies); + get + { + return _types.Value; + } } public List<Registry> Registries { get { return _registries; } } Modified: trunk/Source/StructureMap/StructureMap.csproj =================================================================== --- trunk/Source/StructureMap/StructureMap.csproj 2009-12-26 05:45:56 UTC (rev 296) +++ trunk/Source/StructureMap/StructureMap.csproj 2009-12-26 17:37:30 UTC (rev 297) @@ -356,9 +356,12 @@ <Compile Include="ErrorMessages.cs" /> <Compile Include="Example.cs" /> <Compile Include="Extensions.cs" /> + <Compile Include="Graph\CompositeFilter.cs" /> + <Compile Include="Graph\CompositePredicate.cs" /> <Compile Include="Graph\FamilyAttributeScanner.cs" /> <Compile Include="Graph\FindAllTypesFilter.cs" /> <Compile Include="Graph\FindRegistriesScanner.cs" /> + <Compile Include="Graph\IAssemblyScanner.cs" /> <Compile Include="Graph\IHeavyweightTypeScanner.cs" /> <Compile Include="Graph\ITypeScanner.cs" /> <Compile Include="Graph\PluggableAttributeScanner.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |