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