annotate Extensions/JointureAddOn/Emit/FunctionFactory.cs @ 4:f757da6161a1

!bug 100 + 2h fixed gregression
author cin
date Sun, 24 Aug 2014 17:57:42 +0400
parents f990fcb411a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1 using System;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2 using System.Collections.Generic;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3 using System.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4 using System.Linq.Expressions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 using System.Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6 using System.Reflection.Emit;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8 namespace BLToolkit.Emit
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 /// Creates and compiles types instances and methods using expressions, IL code generation
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13 /// <remarks>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14 /// Inspired from:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 /// http://abhi.dcmembers.com/blog/2009/03/25/lambda-based-reflection-vs-normal-reflection-vs-direct-call-4/
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16 /// </remarks>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17 public static class FunctionFactory
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 #region Delegates
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21 public delegate object GenericGetter(object target);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23 public delegate void GenericSetter(object target, object value);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 #region Nested type: Il
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29 public static class Il
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 public static object CreateInstance(Type type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 InstantiateObjectHandler instantiateObjectHandler =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34 DynamicMethodCompiler.CreateInstantiateObjectHandler(type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36 return instantiateObjectHandler();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 public static T CreateInstance<T>()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41 return (T) CreateInstance(typeof (T));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44 public static SetHandler CreateSetHandler(Type type, string property)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 PropertyInfo propertyInfo = type.GetProperty(property);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47 return CreateSetHandler(type, propertyInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 public static SetHandler CreateSetHandler(Type type, PropertyInfo propertyInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52 SetHandler setHandler = DynamicMethodCompiler.CreateSetHandler(type, propertyInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 return setHandler;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56 public static SetHandler CreateSetHandler<T>(string property)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 return CreateSetHandler(typeof (T), property);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61 public static GetHandler CreateGetHandler(Type type, PropertyInfo propertyInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 GetHandler getHandler = DynamicMethodCompiler.CreateGetHandler(type, propertyInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64 return getHandler;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67 public static GetHandler CreateGetHandler<T>(PropertyInfo propertyInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 return CreateGetHandler(typeof (T), propertyInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72 public static GetHandler CreateGetHandler<T>(string property)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 PropertyInfo propertyInfo = typeof (T).GetProperty(property);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75 return CreateGetHandler<T>(propertyInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78 ///
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79 /// Creates a dynamic setter for the property
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80 ///
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81 public static GenericSetter CreateSetMethod(PropertyInfo propertyInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 /*
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84 * If there's no setter return null
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85 */
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86 MethodInfo setMethod = propertyInfo.GetSetMethod();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87 if (setMethod == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 /*
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91 * Create the dynamic method
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92 */
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93 var arguments = new Type[2];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94 arguments[0] = arguments[1] = typeof (object);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 var setter = new DynamicMethod(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97 String.Concat("_Set", propertyInfo.Name, "_"),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 typeof (void), arguments, propertyInfo.DeclaringType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99 ILGenerator generator = setter.GetILGenerator();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 generator.Emit(OpCodes.Ldarg_0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101 generator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102 generator.Emit(OpCodes.Ldarg_1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104 if (propertyInfo.PropertyType.IsClass)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 generator.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107 generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 generator.EmitCall(OpCodes.Callvirt, setMethod, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110 generator.Emit(OpCodes.Ret);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 /*
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 * Create the delegate and return it
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114 */
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115 return (GenericSetter) setter.CreateDelegate(typeof (GenericSetter));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 ///
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119 /// Creates a dynamic getter for the property
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120 ///
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121 public static GenericGetter CreateGetMethod(PropertyInfo propertyInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 /*
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 * If there's no getter return null
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125 */
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126 MethodInfo getMethod = propertyInfo.GetGetMethod();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127 if (getMethod == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130 /*
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131 * Create the dynamic method
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132 */
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 var arguments = new Type[1];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 arguments[0] = typeof (object);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 var getter = new DynamicMethod(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137 String.Concat("_Get", propertyInfo.Name, "_"),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138 typeof (object), arguments, propertyInfo.DeclaringType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140 ILGenerator generator = getter.GetILGenerator();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141 generator.DeclareLocal(typeof (object));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142 generator.Emit(OpCodes.Ldarg_0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143 generator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144 generator.EmitCall(OpCodes.Callvirt, getMethod, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 if (!propertyInfo.PropertyType.IsClass)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147 generator.Emit(OpCodes.Box, propertyInfo.PropertyType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 generator.Emit(OpCodes.Ret);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151 /*
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152 * Create the delegate and return it
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153 */
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 return (GenericGetter) getter.CreateDelegate(typeof (GenericGetter));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160 #region Nested type: Lambda
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162 public static class Lambda
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164 public static T CreateInstance<T>()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166 return InstanceCreator<T>.CreateInstance();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 public static List<T> CreateListInstance<T>()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171 return InstanceCreator<T>.CreateListInstance();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
173
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
174 public static Action<T, TValue> BuildSet<T, TValue>(string property)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
175 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
176 string[] props = property.Split('.');
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
177 Type type = typeof (T);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
178 ParameterExpression arg = Expression.Parameter(type, "x");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
179 ParameterExpression valArg = Expression.Parameter(typeof (TValue), "val");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
180 Expression expr = arg;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
181 foreach (string prop in props.Take(props.Length - 1))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
182 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
183 // use reflection (not ComponentModel) to mirror LINQ
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
184 PropertyInfo pi = type.GetProperty(prop);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
185 expr = Expression.Property(expr, pi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
186 type = pi.PropertyType;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
187 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
188 // final property set...
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
189 PropertyInfo finalProp = type.GetProperty(props.Last());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
190 MethodInfo setter = finalProp.GetSetMethod();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
191 expr = Expression.Call(expr, setter, valArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
192 return Expression.Lambda<Action<T, TValue>>(expr, arg, valArg).Compile();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
193 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
194
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
195 public static Func<T, TValue> BuildGet<T, TValue>(string property)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
196 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
197 string[] props = property.Split('.');
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
198 Type type = typeof (T);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
199 ParameterExpression arg = Expression.Parameter(type, "x");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
200 Expression expr = arg;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
201 foreach (string prop in props)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
202 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
203 // use reflection (not ComponentModel) to mirror LINQ
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
204 PropertyInfo pi = type.GetProperty(prop);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
205 expr = Expression.Property(expr, pi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
206 type = pi.PropertyType;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
207 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
208 return Expression.Lambda<Func<T, TValue>>(expr, arg).Compile();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
209 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
210
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
211 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
212 /// Creates a compiled delegate function for the specified type and method name
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
213 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
214 /// <typeparam name="TFunc">Delegate Func to create</typeparam>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
215 /// <param name="obj">Constant to get method from</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
216 /// <param name="methodName">Method to examine</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
217 /// <returns>Delegate function of the specified methodname</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
218 public static TFunc CreateFunc<TFunc>(object obj, string methodName)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
219 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
220 var args = new List<ParameterExpression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
221
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
222 Type targetType = obj.GetType();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
223 MethodInfo minfo = targetType.GetMethod(methodName,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
224 BindingFlags.Instance | BindingFlags.Public |
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
225 BindingFlags.SetProperty);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
226
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
227 if (minfo != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
228 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
229 ConstantExpression target = Expression.Constant(obj);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
230 foreach (ParameterInfo arg in minfo.GetParameters())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
231 args.Add(Expression.Parameter(arg.ParameterType, arg.Name));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
232 MethodCallExpression methodinvokeExpression = Expression.Call(target, minfo, args.ToArray());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
233 Expression<TFunc> lambda = Expression.Lambda<TFunc>(methodinvokeExpression, args.ToArray());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
234
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
235 //now the following Lambda is created:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
236 // (TArg1, TArg2) => obj.MethodName(TArg1, TArg2);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
237
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
238 return lambda.Compile();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
239 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
240 return default(TFunc);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
241 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
242
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
243 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
244 /// Creates a compiled delegate function using expressions,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
245 /// the first Func{TObject,TReturn} parameter must be the constant to be passed in
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
246 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
247 /// <typeparam name="TFunc">Delegate Func to create</typeparam>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
248 /// <param name="targetType">Type of constant to pass in to the Func</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
249 /// <param name="methodName">Method to examine</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
250 /// <returns>Delegate function of the specified methodname</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
251 /// <example>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
252 /// The function Func{TType,TArg1,TArg2} with a method name of "CallMe" would create the following
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
253 /// lambda:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
254 /// <code>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
255 /// (TType, TArg1, TArg2) => TType.CallMe(TArg1, TArg2);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
256 /// </code>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
257 /// </example>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
258 public static TFunc CreateFunc<TFunc>(Type targetType, string methodName)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
259 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
260 var args = new List<ParameterExpression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
261 MethodInfo minfo = targetType.GetMethod(methodName,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
262 BindingFlags.Instance | BindingFlags.Public |
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
263 BindingFlags.SetProperty);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
264
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
265 if (minfo != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
266 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
267 Type objectType = typeof (TFunc).GetGenericArguments().First();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
268 ParameterExpression targetParam = Expression.Parameter(objectType, "a");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
269
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
270 if (!targetType.IsAssignableFrom(objectType))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
271 throw new InvalidCastException(string.Format("{0} cannot be cast to {1}", targetType.Name,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
272 objectType.Name));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
273
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
274 UnaryExpression target = Expression.Convert(targetParam, targetType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
275 foreach (ParameterInfo arg in minfo.GetParameters())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
276 args.Add(Expression.Parameter(arg.ParameterType, arg.Name));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
277
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
278 MethodCallExpression methodinvokeExpression = Expression.Call(target, minfo, args.ToArray());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
279 Expression<TFunc> lambda = Expression.Lambda<TFunc>(methodinvokeExpression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
280 new[] {targetParam}.Concat(args));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
281
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
282 //now the following Lambda is created:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
283 // (a, TArg1, TArg2) => a.MethodName(TArg1, TArg2);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
284
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
285 return lambda.Compile();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
286 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
287 return default(TFunc);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
288 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
289
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
290 #region Nested type: InstanceCreator
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
291
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
292 private static class InstanceCreator<T>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
293 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
294 public static readonly Func<T> CreateInstance =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
295 Expression.Lambda<Func<T>>(Expression.New(typeof (T))).Compile();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
296
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
297 public static readonly Func<List<T>> CreateListInstance =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
298 Expression.Lambda<Func<List<T>>>(Expression.New(typeof(List<T>))).Compile();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
299 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
300
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
301 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
302 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
303
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
304 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
305
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
306 #region Nested type: Remote
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
307
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
308 public static class Remote
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
309 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
310 public static T CreateInstance<T>()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
311 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
312 return Activator.CreateInstance<T>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
313 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
314
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
315 public static object CreateInstance(Type type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
316 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
317 return Activator.CreateInstance(type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
318 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
319 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
320
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
321 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
322 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
323 }