PageRenderTime 95ms CodeModel.GetById 90ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Manos/Manos.Routing/ParameterizedActionFactory.cs

http://github.com/jacksonh/manos
C# | 142 lines | 97 code | 18 blank | 27 comment | 11 complexity | 053fa4d2ef05fc197d703967f246b60e MD5 | raw file
  1//
  2// Copyright (C) 2010 Jackson Harper (jackson@manosdemono.com)
  3//
  4// Permission is hereby granted, free of charge, to any person obtaining
  5// a copy of this software and associated documentation files (the
  6// "Software"), to deal in the Software without restriction, including
  7// without limitation the rights to use, copy, modify, merge, publish,
  8// distribute, sublicense, and/or sell copies of the Software, and to
  9// permit persons to whom the Software is furnished to do so, subject to
 10// the following conditions:
 11// 
 12// The above copyright notice and this permission notice shall be
 13// included in all copies or substantial portions of the Software.
 14// 
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 16// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 17// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 18// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 19// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 20// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 21// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 22//
 23//
 24
 25
 26
 27using System;
 28using System.Reflection;
 29using System.Reflection.Emit;
 30
 31//
 32// Adapted from example code here:
 33// http://www.codeproject.com/KB/cs/FastInvokerWrapper.aspx
 34//
 35
 36namespace Manos.Routing
 37{
 38	public static class ParameterizedActionFactory
 39	{
 40		public static ParameterizedAction CreateAction (MethodInfo method)
 41		{
 42			DynamicMethod dynamic = new DynamicMethod (String.Empty, typeof (void), 
 43			                                           new Type [] { typeof(object), typeof(object[]) }, 
 44                          							   method.DeclaringType.Module);
 45			
 46			ILGenerator codegen = dynamic.GetILGenerator ();
 47            ParameterInfo [] parameters = method.GetParameters ();
 48            
 49			Type [] param_types = new Type [parameters.Length];
 50            for (int i = 0; i < param_types.Length; i++)
 51            {
 52                if (parameters [i].ParameterType.IsByRef) {
 53					Console.Error.WriteLine ("By Ref parameters are not allowed in Action signatures.");
 54                    return null;
 55				}
 56                param_types [i] = parameters [i].ParameterType;
 57            }
 58           
 59			LocalBuilder [] locals = new LocalBuilder [param_types.Length];
 60			for (int i = 0; i < param_types.Length; i++) {
 61                locals [i] = codegen.DeclareLocal (param_types [i], true);
 62            }
 63            
 64			for (int i = 0; i < param_types.Length; i++) {
 65                codegen.Emit (OpCodes.Ldarg_1);
 66                EmitFastInt (codegen, i);
 67                codegen.Emit (OpCodes.Ldelem_Ref);
 68                EmitCastToReference (codegen, param_types [i]);
 69                codegen.Emit (OpCodes.Stloc, locals [i]);
 70            }
 71			
 72			if (!method.IsStatic) {
 73                codegen.Emit (OpCodes.Ldarg_0);
 74            }
 75			
 76			for (int i = 0; i < param_types.Length; i++) {
 77                codegen.Emit (OpCodes.Ldloc, locals [i]);
 78            }
 79			
 80			if (method.IsStatic)
 81                codegen.EmitCall (OpCodes.Call, method, null);
 82            else
 83                codegen.EmitCall(OpCodes.Callvirt, method, null);
 84            
 85			codegen.Emit (OpCodes.Ret);
 86            
 87			ParameterizedAction action = (ParameterizedAction) dynamic.CreateDelegate (typeof(ParameterizedAction));
 88            return action;
 89		}
 90		
 91		private static void EmitCastToReference (ILGenerator il, Type type)
 92        {
 93            if (type.IsValueType)
 94                il.Emit (OpCodes.Unbox_Any, type);
 95            else
 96                il.Emit (OpCodes.Castclass, type);
 97        }
 98		
 99		private static void EmitFastInt(ILGenerator il, int value)
100        {
101            switch (value)
102            {
103                case -1:
104                    il.Emit (OpCodes.Ldc_I4_M1);
105                    return;
106                case 0:
107                    il.Emit (OpCodes.Ldc_I4_0);
108                    return;
109                case 1:
110                    il.Emit (OpCodes.Ldc_I4_1);
111                    return;
112                case 2:
113                    il.Emit (OpCodes.Ldc_I4_2);
114                    return;
115                case 3:
116                    il.Emit (OpCodes.Ldc_I4_3);
117                    return;
118                case 4:
119                    il.Emit (OpCodes.Ldc_I4_4);
120                    return;
121                case 5:
122                    il.Emit (OpCodes.Ldc_I4_5);
123                    return;
124                case 6:
125                    il.Emit (OpCodes.Ldc_I4_6);
126                    return;
127                case 7:
128                    il.Emit (OpCodes.Ldc_I4_7);
129                    return;
130                case 8:
131                    il.Emit (OpCodes.Ldc_I4_8);
132                    return;
133            }
134
135            if (value > -129 && value < 128)
136                il.Emit (OpCodes.Ldc_I4_S, (SByte) value);
137            else
138                il.Emit (OpCodes.Ldc_I4, value);
139        }
140	}
141}
142