From: <jer...@us...> - 2009-12-26 19:29:17
|
Revision: 301 http://structuremap.svn.sourceforge.net/structuremap/?rev=301&view=rev Author: jeremydmiller Date: 2009-12-26 19:29:05 +0000 (Sat, 26 Dec 2009) Log Message: ----------- converted the DefaultConventionScanner to be a RegistrationConvention Modified Paths: -------------- trunk/Source/StructureMap/Configuration/DSL/Expressions/GenericFamilyExpression.cs trunk/Source/StructureMap/Configuration/DSL/Registry.cs trunk/Source/StructureMap/Graph/AssemblyScanner.cs trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs trunk/Source/StructureMap/Graph/IAssemblyScanner.cs trunk/Source/StructureMap/Graph/ITypeScanner.cs trunk/Source/StructureMap/TypeExtensions.cs trunk/Source/StructureMap.Testing/Graph/DefaultConventionScanningTester.cs trunk/Source/StructureMap.Testing/Graph/GenericsPluginGraphTester.cs Modified: trunk/Source/StructureMap/Configuration/DSL/Expressions/GenericFamilyExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Expressions/GenericFamilyExpression.cs 2009-12-26 18:39:40 UTC (rev 300) +++ trunk/Source/StructureMap/Configuration/DSL/Expressions/GenericFamilyExpression.cs 2009-12-26 19:29:05 UTC (rev 301) @@ -88,6 +88,7 @@ /// </summary> /// <param name="concreteType"></param> /// <returns></returns> + [Obsolete("Switch to Add()")] public ConfiguredInstance AddType(Type concreteType) { var instance = new ConfiguredInstance(concreteType); @@ -97,7 +98,19 @@ return instance; } + /// <summary> + /// Shortcut method to add an additional Instance to this Plugin Type + /// as just a Concrete Type. This will only work if the Concrete Type + /// has no primitive constructor or mandatory Setter arguments. + /// </summary> + /// <param name="concreteType"></param> + /// <returns></returns> + public ConfiguredInstance Add(Type concreteType) + { + return AddType(concreteType); + } + public GenericFamilyExpression Add(Instance instance) { return alterAndContinue(family => family.AddInstance(instance)); Modified: trunk/Source/StructureMap/Configuration/DSL/Registry.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Registry.cs 2009-12-26 18:39:40 UTC (rev 300) +++ trunk/Source/StructureMap/Configuration/DSL/Registry.cs 2009-12-26 19:29:05 UTC (rev 301) @@ -8,6 +8,225 @@ namespace StructureMap.Configuration.DSL { + public interface IRegistry + { + /// <summary> + /// Adds the concreteType as an Instance of the pluginType + /// </summary> + /// <param name="pluginType"></param> + /// <param name="concreteType"></param> + void AddType(Type pluginType, Type concreteType); + + /// <summary> + /// Adds the concreteType as an Instance of the pluginType with a name + /// </summary> + /// <param name="pluginType"></param> + /// <param name="concreteType"></param> + /// <param name="name"></param> + void AddType(Type pluginType, Type concreteType, string name); + + /// <summary> + /// Add the pluggedType as an instance to any configured pluginType where pluggedType + /// could be assigned to the pluginType + /// </summary> + /// <param name="pluggedType"></param> + void AddType(Type pluggedType); + + /// <summary> + /// Imports the configuration from another registry into this registry. + /// </summary> + /// <typeparam name="T"></typeparam> + void IncludeRegistry<T>() where T : Registry, new(); + + /// <summary> + /// Imports the configuration from another registry into this registry. + /// </summary> + /// <param name="registry"></param> + void IncludeRegistry(Registry registry); + + /// <summary> + /// Expression Builder used to define policies for a PluginType including + /// Scoping, the Default Instance, and interception. BuildInstancesOf() + /// and ForRequestedType() are synonyms + /// </summary> + /// <typeparam name="PLUGINTYPE"></typeparam> + /// <returns></returns> + [Obsolete("Change to For<T>()")] + CreatePluginFamilyExpression<PLUGINTYPE> BuildInstancesOf<PLUGINTYPE>(); + + /// <summary> + /// Expression Builder used to define policies for a PluginType including + /// Scoping, the Default Instance, and interception. This method is specifically + /// meant for registering open generic types + /// </summary> + /// <returns></returns> + [Obsolete("Change to For(pluginType)")] + GenericFamilyExpression ForRequestedType(Type pluginType); + + /// <summary> + /// This method is a shortcut for specifying the default constructor and + /// setter arguments for a ConcreteType. ForConcreteType is shorthand for: + /// ForRequestedType[T]().TheDefault.Is.OfConcreteType[T].************** + /// when the PluginType and ConcreteType are the same Type + /// </summary> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + Registry.BuildWithExpression<T> ForConcreteType<T>(); + + /// <summary> + /// Expression Builder used to define policies for a PluginType including + /// Scoping, the Default Instance, and interception. BuildInstancesOf() + /// and ForRequestedType() are synonyms + /// </summary> + /// <typeparam name="PLUGINTYPE"></typeparam> + /// <returns></returns> + [Obsolete("Change to For<T>()")] + CreatePluginFamilyExpression<PLUGINTYPE> ForRequestedType<PLUGINTYPE>(); + + /// <summary> + /// Convenience method. Equivalent of ForRequestedType[PluginType]().AsSingletons() + /// </summary> + /// <typeparam name="PLUGINTYPE"></typeparam> + /// <returns></returns> + CreatePluginFamilyExpression<PLUGINTYPE> ForSingletonOf<PLUGINTYPE>(); + + /// <summary> + /// Uses the configuration expressions of this Registry to create a PluginGraph + /// object that could be used to initialize a Container. This method is + /// mostly for internal usage, but might be helpful for diagnostics + /// </summary> + /// <returns></returns> + PluginGraph Build(); + + /// <summary> + /// Adds an additional, non-Default Instance to the PluginType T. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + [Obsolete("Prefer For<T>().Add() instead")] + IsExpression<T> InstanceOf<T>(); + + /// <summary> + /// Adds an additional, non-Default Instance to the designated pluginType + /// This method is mostly meant for open generic types + /// </summary> + /// <param name="pluginType"></param> + /// <returns></returns> + [Obsolete("Prefer For(type).Add() instead")] + GenericIsExpression InstanceOf(Type pluginType); + + /// <summary> + /// Expression Builder to define the defaults for a named Profile. Each call + /// to CreateProfile is additive. + /// </summary> + /// <param name="profileName"></param> + /// <returns></returns> + ProfileExpression CreateProfile(string profileName); + + /// <summary> + /// An alternative way to use CreateProfile that uses ProfileExpression + /// as a Nested Closure. This usage will result in cleaner code for + /// multiple declarations + /// </summary> + /// <param name="profileName"></param> + /// <param name="action"></param> + void CreateProfile(string profileName, Action<ProfileExpression> action); + + /// <summary> + /// Registers a new TypeInterceptor object with the Container + /// </summary> + /// <param name="interceptor"></param> + void RegisterInterceptor(TypeInterceptor interceptor); + + /// <summary> + /// Allows you to define a TypeInterceptor inline with Lambdas or anonymous delegates + /// </summary> + /// <param name="match"></param> + /// <returns></returns> + /// <example> + /// IfTypeMatches( ... ).InterceptWith( o => new ObjectWrapper(o) ); + /// </example> + MatchedTypeInterceptor IfTypeMatches(Predicate<Type> match); + + /// <summary> + /// Designates a policy for scanning assemblies to auto + /// register types + /// </summary> + /// <returns></returns> + void Scan(Action<IAssemblyScanner> action); + + /// <summary> + /// Directs StructureMap to always inject dependencies into any and all public Setter properties + /// of the type PLUGINTYPE. + /// </summary> + /// <typeparam name="PLUGINTYPE"></typeparam> + /// <returns></returns> + CreatePluginFamilyExpression<PLUGINTYPE> FillAllPropertiesOfType<PLUGINTYPE>(); + + /// <summary> + /// Creates automatic "policies" for which public setters are considered mandatory + /// properties by StructureMap that will be "setter injected" as part of the + /// construction process. + /// </summary> + /// <param name="action"></param> + void SetAllProperties(Action<SetterConvention> action); + + /// <summary> + /// Use to programmatically select the constructor function of a concrete + /// class. Applies globally to all Containers in a single AppDomain. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="expression"></param> + void SelectConstructor<T>(Expression<Func<T>> expression); + + /// <summary> + /// All requests For the "TO" types will be filled by fetching the "FROM" + /// type and casting it to "TO" + /// GetInstance(typeof(TO)) basically becomes (TO)GetInstance(typeof(FROM)) + /// </summary> + /// <typeparam name="FROM"></typeparam> + /// <typeparam name="TO"></typeparam> + void Forward<FROM, TO>() where FROM : class where TO : class; + + /// <summary> + /// Syntactic Sugar for saying ForRequestedType().TheDefault.IsThis( @object ) + /// </summary> + /// <typeparam name="PLUGINTYPE"></typeparam> + /// <param name="object"></param> + void Register<PLUGINTYPE>(PLUGINTYPE @object); + + /// <summary> + /// Syntactic Sugar for saying ForRequestedType().TheDefault.IsThis( instance ) + /// </summary> + /// <typeparam name="PLUGINTYPE"></typeparam> + /// <param name="instance"></param> + void Register<PLUGINTYPE>(Instance instance); + + /// <summary> + /// Shorthand for ForRequestedType<PLUGINTYPE>() + /// </summary> + /// <typeparam name="PLUGINTYPE"></typeparam> + /// <returns></returns> + CreatePluginFamilyExpression<PLUGINTYPE> For<PLUGINTYPE>(); + + /// <summary> + /// Shorthand for ForRequestedType(pluginType) + /// </summary> + /// <param name="pluginType"></param> + /// <returns></returns> + GenericFamilyExpression For(Type pluginType); + + /// <summary> + /// Shortcut to make StructureMap return the default object of U casted to T + /// whenever T is requested. I.e.: + /// For<T>().TheDefault.Is.ConstructedBy(c => c.GetInstance<U>() as T); + /// </summary> + /// <typeparam name="T"></typeparam> + /// <typeparam name="U"></typeparam> + /// <returns></returns> + LambdaInstance<T> Redirect<T, U>() where T : class where U : class; + } + /// <summary> /// A Registry class provides methods and grammars for configuring a Container or ObjectFactory. /// Using a Registry subclass is the recommended way of configuring a StructureMap Container. @@ -21,12 +240,43 @@ /// } /// } /// </example> - public class Registry + public class Registry : IRegistry { private readonly List<Action<PluginGraph>> _actions = new List<Action<PluginGraph>>(); private readonly List<Action> _basicActions = new List<Action>(); /// <summary> + /// Adds the concreteType as an Instance of the pluginType + /// </summary> + /// <param name="pluginType"></param> + /// <param name="concreteType"></param> + public void AddType(Type pluginType, Type concreteType) + { + _actions.Add(g => g.AddType(pluginType, concreteType)); + } + + /// <summary> + /// Adds the concreteType as an Instance of the pluginType with a name + /// </summary> + /// <param name="pluginType"></param> + /// <param name="concreteType"></param> + /// <param name="name"></param> + public void AddType(Type pluginType, Type concreteType, string name) + { + _actions.Add(g => g.AddType(pluginType, concreteType, name)); + } + + /// <summary> + /// Add the pluggedType as an instance to any configured pluginType where pluggedType + /// could be assigned to the pluginType + /// </summary> + /// <param name="pluggedType"></param> + public void AddType(Type pluggedType) + { + _actions.Add(g => g.AddType(pluggedType)); + } + + /// <summary> /// Imports the configuration from another registry into this registry. /// </summary> /// <typeparam name="T"></typeparam> @@ -315,6 +565,13 @@ PluginCache.GetPlugin(typeof (T)).UseConstructor(expression); } + /// <summary> + /// All requests For the "TO" types will be filled by fetching the "FROM" + /// type and casting it to "TO" + /// GetInstance(typeof(TO)) basically becomes (TO)GetInstance(typeof(FROM)) + /// </summary> + /// <typeparam name="FROM"></typeparam> + /// <typeparam name="TO"></typeparam> public void Forward<FROM, TO>() where FROM : class where TO : class { For<TO>().AddInstances(x => x.ConstructedBy(c => c.GetInstance<FROM>() as TO)); Modified: trunk/Source/StructureMap/Graph/AssemblyScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/AssemblyScanner.cs 2009-12-26 18:39:40 UTC (rev 300) +++ trunk/Source/StructureMap/Graph/AssemblyScanner.cs 2009-12-26 19:29:05 UTC (rev 301) @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Reflection; +using StructureMap.Configuration.DSL; using StructureMap.TypeRules; using StructureMap.Util; @@ -39,6 +40,7 @@ public class AssemblyScanner : IAssemblyScanner { private readonly List<Assembly> _assemblies = new List<Assembly>(); + private readonly List<IRegistrationConvention> _conventions = new List<IRegistrationConvention>(); private readonly CompositeFilter<Type> _filter = new CompositeFilter<Type>(); private readonly ImplementationMap _implementationMap = new ImplementationMap(); @@ -67,18 +69,18 @@ Assembly(AppDomain.CurrentDomain.Load(assemblyName)); } + [Obsolete("Replace ITypeScanner with IRegistrationConvention")] public void With(ITypeScanner scanner) { - if (_scanners.Contains(scanner)) return; - - _scanners.Add(scanner); + _scanners.Fill(scanner); } public void WithDefaultConventions() { - With<DefaultConventionScanner>(); + Convention<DefaultConventionScanner>(); } + [Obsolete("Replace ITypeScanner with IRegistrationConvention")] public void With<T>() where T : ITypeScanner, new() { _scanners.RemoveAll(scanner => scanner is T); @@ -90,6 +92,15 @@ } } + public void Convention<T>() where T : IRegistrationConvention, new() + { + var previous = _conventions.FirstOrDefault(scanner => scanner is T); + if (previous == null) + { + With(new T()); + } + } + public void LookForRegistries() { With<FindRegistriesScanner>(); @@ -206,14 +217,15 @@ public void AssembliesFromPath(string path, Predicate<Assembly> assemblyFilter) { - IEnumerable<string> assemblyPaths = Directory.GetFiles(path).Where(file => - Path.GetExtension(file).Equals( - ".exe", - StringComparison.OrdinalIgnoreCase) - || - Path.GetExtension(file).Equals( - ".dll", - StringComparison.OrdinalIgnoreCase)); + IEnumerable<string> assemblyPaths = Directory.GetFiles(path) + .Where(file => + Path.GetExtension(file).Equals( + ".exe", + StringComparison.OrdinalIgnoreCase) + || + Path.GetExtension(file).Equals( + ".dll", + StringComparison.OrdinalIgnoreCase)); foreach (string assemblyPath in assemblyPaths) { @@ -229,11 +241,23 @@ } } + public void With(IRegistrationConvention convention) + { + _conventions.Fill(convention); + } + internal void ScanForAll(PluginGraph pluginGraph) { + var registry = new Registry(); + pluginGraph.Types.For(_assemblies, _filter).Each( - type => { _scanners.Each(x => x.Process(type, pluginGraph)); }); + type => + { + _scanners.Each(x => x.Process(type, pluginGraph)); + _conventions.Each(c => c.Process(type, registry)); + }); + registry.ConfigurePluginGraph(pluginGraph); _postScanningActions.Each(x => x(pluginGraph)); } Modified: trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs =================================================================== --- trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs 2009-12-26 18:39:40 UTC (rev 300) +++ trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs 2009-12-26 19:29:05 UTC (rev 301) @@ -53,6 +53,9 @@ private static bool checkGenericType(Type pluggedType, Type pluginType) { + if (pluginType.IsAssignableFrom(pluggedType)) return true; + + // check interfaces foreach (Type type in pluggedType.GetInterfaces()) { Modified: trunk/Source/StructureMap/Graph/IAssemblyScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/IAssemblyScanner.cs 2009-12-26 18:39:40 UTC (rev 300) +++ trunk/Source/StructureMap/Graph/IAssemblyScanner.cs 2009-12-26 19:29:05 UTC (rev 301) @@ -185,5 +185,18 @@ /// The filters apply /// </summary> void SingleImplementationsOfInterface(); + + /// <summary> + /// Adds a registration convention to be applied to all the types in this + /// logical "scan" operation + /// </summary> + /// <typeparam name="T"></typeparam> + void Convention<T>() where T : IRegistrationConvention, new(); + + /// <summary> + /// Adds a registration convention to be applied to all the types in this + /// logical "scan" operation + /// </summary> + void With(IRegistrationConvention convention); } } \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/ITypeScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/ITypeScanner.cs 2009-12-26 18:39:40 UTC (rev 300) +++ trunk/Source/StructureMap/Graph/ITypeScanner.cs 2009-12-26 19:29:05 UTC (rev 301) @@ -1,30 +1,33 @@ using System; +using StructureMap.Configuration.DSL; using StructureMap.TypeRules; namespace StructureMap.Graph { + [Obsolete("Favor the new IRegistrationConvention")] public interface ITypeScanner { void Process(Type type, PluginGraph graph); } - public class DefaultConventionScanner : ITypeScanner + public interface IRegistrationConvention { - #region ITypeScanner Members + void Process(Type type, Registry registry); + } - public void Process(Type type, PluginGraph graph) + public class DefaultConventionScanner : IRegistrationConvention + { + public void Process(Type type, Registry registry) { if (!type.IsConcrete()) return; Type pluginType = FindPluginType(type); if (pluginType != null && Constructor.HasConstructors(type)) { - graph.AddType(pluginType, type); + registry.For(pluginType).Add(type); } } - #endregion - public virtual Type FindPluginType(Type concreteType) { string interfaceName = "I" + concreteType.Name; Modified: trunk/Source/StructureMap/TypeExtensions.cs =================================================================== --- trunk/Source/StructureMap/TypeExtensions.cs 2009-12-26 18:39:40 UTC (rev 300) +++ trunk/Source/StructureMap/TypeExtensions.cs 2009-12-26 19:29:05 UTC (rev 301) @@ -172,7 +172,7 @@ return false; } - if (IsOpenGeneric(pluginType)) + if (pluginType.IsOpenGeneric() && pluggedType.IsGenericType) { return GenericsPluginGraph.CanBeCast(pluginType, pluggedType); } Modified: trunk/Source/StructureMap.Testing/Graph/DefaultConventionScanningTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/DefaultConventionScanningTester.cs 2009-12-26 18:39:40 UTC (rev 300) +++ trunk/Source/StructureMap.Testing/Graph/DefaultConventionScanningTester.cs 2009-12-26 19:29:05 UTC (rev 301) @@ -1,5 +1,6 @@ using System; using NUnit.Framework; +using StructureMap.Configuration.DSL; using StructureMap.Graph; namespace StructureMap.Testing.Graph @@ -61,6 +62,14 @@ [TestFixture] public class DefaultConventionScanningTester { + [SetUp] + public void SetUp() + { + PluginCache.ResetAll(); + } + + + [Test] public void FindPluginType() { @@ -77,7 +86,7 @@ registry.Scan(x => { x.TheCallingAssembly(); - x.With<DefaultConventionScanner>(); + x.Convention<DefaultConventionScanner>(); }); }); @@ -105,8 +114,13 @@ { var graph = new PluginGraph(); var scanner = new DefaultConventionScanner(); - scanner.Process(typeof (Convention), graph); + var registry = new Registry(); + + scanner.Process(typeof (Convention), registry); + + registry.ConfigurePluginGraph(graph); + Assert.IsFalse(graph.PluginFamilies.Contains(typeof (IServer))); Assert.IsTrue(graph.PluginFamilies.Contains(typeof (IConvention))); Modified: trunk/Source/StructureMap.Testing/Graph/GenericsPluginGraphTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/GenericsPluginGraphTester.cs 2009-12-26 18:39:40 UTC (rev 300) +++ trunk/Source/StructureMap.Testing/Graph/GenericsPluginGraphTester.cs 2009-12-26 19:29:05 UTC (rev 301) @@ -3,6 +3,7 @@ using NUnit.Framework; using StructureMap.Graph; using StructureMap.Pipeline; +using StructureMap.Testing.Bugs; using StructureMap.Testing.GenericWidgets; namespace StructureMap.Testing.Graph @@ -30,6 +31,12 @@ } [Test] + public void checking_can_be_cast() + { + assertCanBeCast(typeof(IOpenType<>), typeof(OpenType<>)); + } + + [Test] public void BuildAnInstanceManagerFromTemplatedPluginFamily() { var pluginGraph = new PluginGraph(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |