Json.NET
Code Coverage Statistics for Source File

Newtonsoft.Json\Utilities\DynamicReflectionDelegateFactory.cs

Symbol Coverage: 96.70% (88 of 91)

Branch Coverage: 89.74% (35 of 39)

Cyclomatic Complexity Avg: 2.78 Max:9

Code Lines: 96


L V Source
1
#region License
2
// Copyright (c) 2007 James Newton-King
3
//
4
// Permission is hereby granted, free of charge, to any person
5
// obtaining a copy of this software and associated documentation
6
// files (the "Software"), to deal in the Software without
7
// restriction, including without limitation the rights to use,
8
// copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the
10
// Software is furnished to do so, subject to the following
11
// conditions:
12
//
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
// OTHER DEALINGS IN THE SOFTWARE.
24
#endregion
25

  
26
#if !PocketPC && !SILVERLIGHT
27
using System;
28
using System.Collections.Generic;
29
using System.Linq;
30
using System.Reflection;
31
using System.Reflection.Emit;
32
using System.Text;
33
using System.Globalization;
34

  
35
namespace Newtonsoft.Json.Utilities
36
{
37
  internal class DynamicReflectionDelegateFactory : ReflectionDelegateFactory
38
  {
39
 1
    public static DynamicReflectionDelegateFactory Instance = new DynamicReflectionDelegateFactory();
40

  
41
    private static DynamicMethod CreateDynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner)
42
    {
43
 931
      DynamicMethod dynamicMethod = !owner.IsInterface
44
 931
        ? new DynamicMethod(name, returnType, parameterTypes, owner, true)
45
 931
        : new DynamicMethod(name, returnType, parameterTypes, (Module)null, true);
46

  
47
 931
      return dynamicMethod;
48
 931
    }
49

  
50
    public override MethodCall<T, object> CreateMethodCall<T>(MethodBase method)
51
    {
52
 13
      DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType);
53
 13
      ILGenerator generator = dynamicMethod.GetILGenerator();
54

  
55
 13
      ParameterInfo[] args = method.GetParameters();
56

  
57
 13
      Label argsOk = generator.DefineLabel();
58

  
59
 13
      generator.Emit(OpCodes.Ldarg_1);
60
 13
      generator.Emit(OpCodes.Ldlen);
61
 13
      generator.Emit(OpCodes.Ldc_I4, args.Length);
62
 13
      generator.Emit(OpCodes.Beq, argsOk);
63

  
64
 13
      generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(Type.EmptyTypes));
65
 13
      generator.Emit(OpCodes.Throw);
66

  
67
 13
      generator.MarkLabel(argsOk);
68

  
69
 13
      if (!method.IsConstructor && !method.IsStatic)
70
 2
        generator.PushInstance(method.DeclaringType);
71

  
72
 13
      for (int i = 0; i < args.Length; i++)
73
      {
74
 16
        generator.Emit(OpCodes.Ldarg_1);
75
 16
        generator.Emit(OpCodes.Ldc_I4, i);
76
 16
        generator.Emit(OpCodes.Ldelem_Ref);
77

  
78
 16
        generator.UnboxIfNeeded(args[i].ParameterType);
79
      }
80

  
81
 13
      if (method.IsConstructor)
82
 9
        generator.Emit(OpCodes.Newobj, (ConstructorInfo)method);
83
 4
      else if (method.IsFinal || !method.IsVirtual)
84
 4
        generator.CallMethod((MethodInfo)method);
85

  
86
 13
      Type returnType = method.IsConstructor
87
 13
        ? method.DeclaringType
88
 13
        : ((MethodInfo)method).ReturnType;
89

  
90
 13
      if (returnType != typeof(void))
91
 13
        generator.BoxIfNeeded(returnType);
92
      else
93
 0
        generator.Emit(OpCodes.Ldnull);
94

  
95
 13
      generator.Return();
96

  
97
 13
      return (MethodCall<T, object>)dynamicMethod.CreateDelegate(typeof(MethodCall<T, object>));
98
 13
    }
99

  
100
    public override Func<T> CreateDefaultConstructor<T>(Type type)
101
    {
102
 255
      DynamicMethod dynamicMethod = CreateDynamicMethod("Create" + type.FullName, typeof(object), Type.EmptyTypes, type);
103
 255
      dynamicMethod.InitLocals = true;
104
 255
      ILGenerator generator = dynamicMethod.GetILGenerator();
105

  
106
 255
      if (type.IsValueType)
107
      {
108
 46
        generator.DeclareLocal(type);
109
 46
        generator.Emit(OpCodes.Ldloc_0);
110
 46
        generator.Emit(OpCodes.Box, type);
111
      }
112
      else
113
      {
114
 209
        ConstructorInfo constructorInfo =
115
 209
          type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null,
116
 209
                              Type.EmptyTypes, null);
117

  
118
 209
        if (constructorInfo == null)
119
 0
          throw new Exception("Could not get constructor for {0}.".FormatWith(CultureInfo.InvariantCulture, type));
120

  
121
 209
        generator.Emit(OpCodes.Newobj, constructorInfo);
122
      }
123

  
124
 255
      generator.Return();
125

  
126
 255
      return (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
127
 255
    }
128

  
129
    public override Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
130
    {
131
 275
      MethodInfo getMethod = propertyInfo.GetGetMethod(true);
132
 275
      if (getMethod == null)
133
 0
        throw new Exception("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture,
134
 0
                                                                                propertyInfo.Name));
135

  
136
 275
      DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(T), new[] { typeof(object) }, propertyInfo.DeclaringType);
137

  
138
 275
      ILGenerator generator = dynamicMethod.GetILGenerator();
139

  
140
 275
      if (!getMethod.IsStatic)
141
 275
        generator.PushInstance(propertyInfo.DeclaringType);
142

  
143
 275
      generator.CallMethod(getMethod);
144
 275
      generator.BoxIfNeeded(propertyInfo.PropertyType);
145
 275
      generator.Return();
146

  
147
 275
      return (Func<T, object>)dynamicMethod.CreateDelegate(typeof(Func<T, object>));
148
 275
    }
149

  
150
    public override Func<T, object> CreateGet<T>(FieldInfo fieldInfo)
151
    {
152
 101
      DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new[] { typeof(object) }, fieldInfo.DeclaringType);
153

  
154
 101
      ILGenerator generator = dynamicMethod.GetILGenerator();
155

  
156
 101
      if (!fieldInfo.IsStatic)
157
 101
        generator.PushInstance(fieldInfo.DeclaringType);
158

  
159
 101
      generator.Emit(OpCodes.Ldfld, fieldInfo);
160
 101
      generator.BoxIfNeeded(fieldInfo.FieldType);
161
 101
      generator.Return();
162

  
163
 101
      return (Func<T, object>)dynamicMethod.CreateDelegate(typeof(Func<T, object>));
164
 101
    }
165

  
166
    public override Action<T, object> CreateSet<T>(FieldInfo fieldInfo)
167
    {
168
 91
      DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(object), typeof(object) }, fieldInfo.DeclaringType);
169
 91
      ILGenerator generator = dynamicMethod.GetILGenerator();
170

  
171
 91
      if (!fieldInfo.IsStatic)
172
 91
        generator.PushInstance(fieldInfo.DeclaringType);
173

  
174
 91
      generator.Emit(OpCodes.Ldarg_1);
175
 91
      generator.UnboxIfNeeded(fieldInfo.FieldType);
176
 91
      generator.Emit(OpCodes.Stfld, fieldInfo);
177
 91
      generator.Return();
178

  
179
 91
      return (Action<T, object>)dynamicMethod.CreateDelegate(typeof(Action<T, object>));
180
 91
    }
181

  
182
    public override Action<T, object> CreateSet<T>(PropertyInfo propertyInfo)
183
    {
184
 196
      MethodInfo setMethod = propertyInfo.GetSetMethod(true);
185
 196
      DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(object), typeof(object) }, propertyInfo.DeclaringType);
186
 196
      ILGenerator generator = dynamicMethod.GetILGenerator();
187

  
188
 196
      if (!setMethod.IsStatic)
189
 196
        generator.PushInstance(propertyInfo.DeclaringType);
190

  
191
 196
      generator.Emit(OpCodes.Ldarg_1);
192
 196
      generator.UnboxIfNeeded(propertyInfo.PropertyType);
193
 196
      generator.CallMethod(setMethod);
194
 196
      generator.Return();
195

  
196
 196
      return (Action<T, object>)dynamicMethod.CreateDelegate(typeof(Action<T, object>));
197
 196
    }
198
  }
199
}
200
#endif