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