|
From: <jer...@us...> - 2009-12-26 05:33:50
|
Revision: 290
http://structuremap.svn.sourceforge.net/structuremap/?rev=290&view=rev
Author: jeremydmiller
Date: 2009-12-26 05:33:42 +0000 (Sat, 26 Dec 2009)
Log Message:
-----------
The big, big, big switch from IL generation to dynamic Func's. Ding dong, the witch is dead.
Added Paths:
-----------
trunk/Source/StructureMap/Construction/
trunk/Source/StructureMap/Construction/BuilderCompiler.cs
trunk/Source/StructureMap/Construction/ConstructorFunctionBuilder.cs
trunk/Source/StructureMap/Construction/IArguments.cs
trunk/Source/StructureMap/Construction/InstanceBuilder.cs
trunk/Source/StructureMap/Construction/SetterBuilder.cs
Added: trunk/Source/StructureMap/Construction/BuilderCompiler.cs
===================================================================
--- trunk/Source/StructureMap/Construction/BuilderCompiler.cs (rev 0)
+++ trunk/Source/StructureMap/Construction/BuilderCompiler.cs 2009-12-26 05:33:42 UTC (rev 290)
@@ -0,0 +1,113 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using StructureMap.Graph;
+
+namespace StructureMap.Construction
+{
+ public class BuilderCompiler
+ {
+ public static InstanceBuilder CreateBuilder(Plugin plugin)
+ {
+ return getCompiler(plugin).CreateBuilder(plugin);
+ }
+
+ public static Func<IArguments, object> CompileCreator(Plugin plugin)
+ {
+ FuncCompiler compiler = getCompiler(plugin);
+
+ return compiler.Compile(plugin);
+ }
+
+ private static FuncCompiler getCompiler(Plugin plugin)
+ {
+ var compilerType = typeof (FuncCompiler<>).MakeGenericType(plugin.PluggedType);
+ return (FuncCompiler)Activator.CreateInstance(compilerType);
+ }
+
+ public static Action<IArguments, object> CompileBuildUp(Plugin plugin)
+ {
+ FuncCompiler compiler = getCompiler(plugin);
+
+ return compiler.BuildUp(plugin);
+ }
+
+ public interface FuncCompiler
+ {
+ Func<IArguments, object> Compile(Plugin plugin);
+ Action<IArguments, object> BuildUp(Plugin plugin);
+
+ InstanceBuilder CreateBuilder(Plugin plugin);
+ }
+
+ public class FuncCompiler<T> : FuncCompiler
+ {
+ private readonly SetterBuilder<T> _setterBuilder = new SetterBuilder<T>();
+
+ public InstanceBuilder CreateBuilder(Plugin plugin)
+ {
+ var ctor = new ConstructorFunctionBuilder<T>().CreateBuilder(plugin);
+ var setters = this.buildUp(plugin);
+
+ Func<IArguments, object> creator = args =>
+ {
+ var target = ctor(args);
+ setters(args, target);
+ return target;
+ };
+
+ Action<IArguments, object> builder = (args, o) => setters(args, (T) o);
+
+ return new InstanceBuilder(plugin.PluggedType, creator, builder);
+ }
+
+ public Func<IArguments, object> Compile(Plugin plugin)
+ {
+ var ctor = new ConstructorFunctionBuilder<T>().CreateBuilder(plugin);
+ var buildUp = this.buildUp(plugin);
+
+ return args =>
+ {
+ // Call the constructor
+ var target = ctor(args);
+ buildUp(args, target);
+
+ return target;
+ };
+ }
+
+ private Action<IArguments, T> buildUp(Plugin plugin)
+ {
+ var mandatories = plugin.Setters.Where(x => x.IsMandatory)
+ .Select(x => _setterBuilder.BuildMandatorySetter((PropertyInfo)x.Property))
+ .ToArray();
+
+
+ var optionals = plugin.Setters.Where(x => !x.IsMandatory)
+ .Select(x => _setterBuilder.BuildOptionalSetter(x.Property))
+ .ToArray();
+
+ return (args, target) =>
+ {
+ // Call the mandatory setters
+ for (int i = 0; i < mandatories.Length; i++)
+ {
+ mandatories[i](args, target);
+ }
+
+ // Call the optional setters
+ for (int i = 0; i < optionals.Length; i++)
+ {
+ optionals[i](args, target);
+ }
+ };
+ }
+
+ public Action<IArguments, object> BuildUp(Plugin plugin)
+ {
+ var func = buildUp(plugin);
+ return (args, raw) => func(args, (T)raw);
+ }
+ }
+ }
+}
\ No newline at end of file
Added: trunk/Source/StructureMap/Construction/ConstructorFunctionBuilder.cs
===================================================================
--- trunk/Source/StructureMap/Construction/ConstructorFunctionBuilder.cs (rev 0)
+++ trunk/Source/StructureMap/Construction/ConstructorFunctionBuilder.cs 2009-12-26 05:33:42 UTC (rev 290)
@@ -0,0 +1,38 @@
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using StructureMap.Graph;
+
+namespace StructureMap.Construction
+{
+ public class ConstructorFunctionBuilder<T>
+ {
+ public Func<IArguments, T> CreateBuilder()
+ {
+ Plugin plugin = PluginCache.GetPlugin(typeof (T));
+ return CreateBuilder(plugin);
+ }
+
+ public Func<IArguments, T> CreateBuilder(Plugin plugin)
+ {
+ ConstructorInfo constructor = plugin.GetConstructor();
+
+ var args = Expression.Parameter(typeof (IArguments), "x");
+
+
+ var arguments = constructor.GetParameters().Select(param => ToParameterValueGetter(args, param.ParameterType, param.Name));
+
+ var ctorCall = Expression.New(constructor, arguments);
+
+ var lambda = Expression.Lambda(typeof (Func<IArguments, T>), ctorCall, args);
+ return (Func<IArguments, T>) lambda.Compile();
+ }
+
+ public static Expression ToParameterValueGetter(ParameterExpression args, Type type, string argName)
+ {
+ MethodInfo method = typeof(IArguments).GetMethod("Get").MakeGenericMethod(type);
+ return Expression.Call(args, method, Expression.Constant(argName));
+ }
+ }
+}
\ No newline at end of file
Added: trunk/Source/StructureMap/Construction/IArguments.cs
===================================================================
--- trunk/Source/StructureMap/Construction/IArguments.cs (rev 0)
+++ trunk/Source/StructureMap/Construction/IArguments.cs 2009-12-26 05:33:42 UTC (rev 290)
@@ -0,0 +1,8 @@
+namespace StructureMap.Construction
+{
+ public interface IArguments
+ {
+ T Get<T>(string propertyName);
+ bool Has(string propertyName);
+ }
+}
\ No newline at end of file
Copied: trunk/Source/StructureMap/Construction/InstanceBuilder.cs (from rev 284, trunk/Source/StructureMap/InstanceBuilder.cs)
===================================================================
--- trunk/Source/StructureMap/Construction/InstanceBuilder.cs (rev 0)
+++ trunk/Source/StructureMap/Construction/InstanceBuilder.cs 2009-12-26 05:33:42 UTC (rev 290)
@@ -0,0 +1,46 @@
+using System;
+using StructureMap.Pipeline;
+
+namespace StructureMap.Construction
+{
+ public interface IInstanceBuilder
+ {
+ Type PluggedType { get; }
+ object BuildInstance(IArguments args);
+ void BuildUp(IArguments args, object target);
+ }
+
+ /// <summary>
+ /// Base class for creating an object instance from an InstanceMemento. SubClasses are
+ /// emitted for each concrete Plugin with constructor parameters.
+ /// </summary>
+ public class InstanceBuilder : IInstanceBuilder
+ {
+ private readonly Type _pluggedType;
+ private readonly Func<IArguments, object> _constructor;
+ private readonly Action<IArguments, object> _buildUp;
+
+ public InstanceBuilder(Type pluggedType, Func<IArguments, object> constructor, Action<IArguments, object> buildUp)
+ {
+ _pluggedType = pluggedType;
+ _constructor = constructor;
+ _buildUp = buildUp;
+ }
+
+ public Type PluggedType { get
+ {
+ return _pluggedType;
+ }
+ }
+
+ public virtual object BuildInstance(IArguments args)
+ {
+ return _constructor(args);
+ }
+
+ public virtual void BuildUp(IArguments args, object target)
+ {
+ _buildUp(args, target);
+ }
+ }
+}
\ No newline at end of file
Added: trunk/Source/StructureMap/Construction/SetterBuilder.cs
===================================================================
--- trunk/Source/StructureMap/Construction/SetterBuilder.cs (rev 0)
+++ trunk/Source/StructureMap/Construction/SetterBuilder.cs 2009-12-26 05:33:42 UTC (rev 290)
@@ -0,0 +1,47 @@
+using System;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace StructureMap.Construction
+{
+ public class SetterBuilder<T>
+ {
+ public Action<IArguments, T> BuildMandatorySetter(string propertyName)
+ {
+ PropertyInfo property = typeof (T).GetProperty(propertyName);
+ return BuildMandatorySetter(property);
+ }
+
+ public Action<IArguments, T> BuildMandatorySetter(PropertyInfo property)
+ {
+ var args = Expression.Parameter(typeof (IArguments), "args");
+ var target = Expression.Parameter(typeof (T), "target");
+
+
+ var getValue = ConstructorFunctionBuilder<T>.ToParameterValueGetter(args, property.PropertyType, property.Name);
+ var method = property.GetSetMethod();
+
+ var callSetMethod = Expression.Call(target, method, getValue);
+
+ var lambda = Expression.Lambda(typeof (Action<IArguments, T>), callSetMethod, args, target);
+
+ return (Action<IArguments, T>) lambda.Compile();
+ }
+
+ public Action<IArguments, T> BuildOptionalSetter(PropertyInfo property)
+ {
+ var name = property.Name;
+ var func = BuildMandatorySetter(property);
+ return (args, target) =>
+ {
+ if (args.Has(name)) func(args, target);
+ };
+ }
+
+ public Action<IArguments, T> BuildOptionalSetter(string propertyName)
+ {
+ PropertyInfo property = typeof(T).GetProperty(propertyName);
+ return BuildOptionalSetter(property);
+ }
+ }
+}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|