CSLA.NET 5.4.2
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
DynamicMethodHandlerFactory.cs
Go to the documentation of this file.
1#if !IOS
2//-----------------------------------------------------------------------
3// <copyright file="DynamicMethodHandlerFactory.cs" company="Marimer LLC">
4// Copyright (c) Marimer LLC. All rights reserved.
5// Website: https://cslanet.com
6// </copyright>
7// <summary>Delegate for a dynamic constructor method.</summary>
8//-----------------------------------------------------------------------
9using System;
10using System.Linq;
11using System.Linq.Expressions;
12using System.Reflection;
13using Csla.Reflection;
14#if !NETFX_CORE
15using System.Reflection.Emit;
16#endif
17using Csla.Properties;
18using System.Collections.Generic;
19
20namespace Csla.Reflection
21{
25 public delegate object DynamicCtorDelegate();
35 public delegate object DynamicMethodDelegate(object target, object[] args);
41 public delegate object DynamicMemberGetDelegate(object target);
47 public delegate void DynamicMemberSetDelegate(object target, object arg);
48
49 internal static class DynamicMethodHandlerFactory
50 {
51 public static DynamicCtorDelegate CreateConstructor(ConstructorInfo constructor)
52 {
53 if (constructor == null)
54 throw new ArgumentNullException("constructor");
55 if (constructor.GetParameters().Length > 0)
56 throw new NotSupportedException(Resources.ConstructorsWithParametersNotSupported);
57
58 Expression body = Expression.New(constructor);
59#if NETFX_CORE
60 if (constructor.DeclaringType.IsValueType())
61#else
62 if (constructor.DeclaringType.IsValueType)
63#endif
64 {
65 body = Expression.Convert(body, typeof(object));
66 }
67
68 return Expression.Lambda<DynamicCtorDelegate>(body).Compile();
69 }
70
71 public static DynamicMethodDelegate CreateMethod(System.Reflection.MethodInfo method)
72 {
73 if (method == null)
74 throw new ArgumentNullException("method");
75
76 ParameterInfo[] pi = method.GetParameters();
77 var targetExpression = Expression.Parameter(typeof(object));
78 var parametersExpression = Expression.Parameter(typeof(object[]));
79
80 Expression[] callParametrs = new Expression[pi.Length];
81 for (int x = 0; x < pi.Length; x++)
82 {
83 callParametrs[x] =
84 Expression.Convert(
85 Expression.ArrayIndex(
86 parametersExpression,
87 Expression.Constant(x)),
88 pi[x].ParameterType);
89 }
90
91 Expression instance = Expression.Convert(targetExpression, method.DeclaringType);
92 Expression body = pi.Length > 0
93 ? Expression.Call(instance, method, callParametrs)
94 : Expression.Call(instance, method);
95
96 if (method.ReturnType == typeof(void))
97 {
98 var target = Expression.Label(typeof(object));
99 var nullRef = Expression.Constant(null);
100 body = Expression.Block(
101 body,
102 Expression.Return(target, nullRef),
103 Expression.Label(target, nullRef));
104 }
105#if NETFX_CORE
106 else if (method.ReturnType.IsValueType())
107#else
108 else if (method.ReturnType.IsValueType)
109#endif
110 {
111 body = Expression.Convert(body, typeof(object));
112 }
113
114 var lambda = Expression.Lambda<DynamicMethodDelegate>(
115 body,
116 targetExpression,
117 parametersExpression);
118
119 return (DynamicMethodDelegate)lambda.Compile();
120 }
121
122 public static DynamicMemberGetDelegate CreatePropertyGetter(PropertyInfo property)
123 {
124 if (property == null)
125 throw new ArgumentNullException("property");
126
127 if (!property.CanRead) return null;
128
129 var target = Expression.Parameter(typeof(object));
130 Expression body = Expression.Property(
131 Expression.Convert(target, property.DeclaringType),
132 property);
133
134#if NETFX_CORE
135 if (property.PropertyType.IsValueType())
136#else
137 if (property.PropertyType.IsValueType)
138#endif
139 {
140 body = Expression.Convert(body, typeof(object));
141 }
142
143 var lambda = Expression.Lambda<DynamicMemberGetDelegate>(
144 body,
145 target);
146
147 return lambda.Compile();
148 }
149
150 public static DynamicMemberSetDelegate CreatePropertySetter(PropertyInfo property)
151 {
152 if (property == null)
153 throw new ArgumentNullException("property");
154
155 if (!property.CanWrite) return null;
156
157 var target = Expression.Parameter(typeof(object));
158 var val = Expression.Parameter(typeof(object));
159
160 Expression body = Expression.Assign(
161 Expression.Property(
162 Expression.Convert(target, property.DeclaringType),
163 property),
164 Expression.Convert(val, property.PropertyType));
165
166 var lambda = Expression.Lambda<DynamicMemberSetDelegate>(
167 body,
168 target,
169 val);
170
171 return lambda.Compile();
172 }
173
174 public static DynamicMemberGetDelegate CreateFieldGetter(FieldInfo field)
175 {
176 if (field == null)
177 throw new ArgumentNullException("field");
178
179 var target = Expression.Parameter(typeof(object));
180 Expression body = Expression.Field(
181 Expression.Convert(target, field.DeclaringType),
182 field);
183
184#if NETFX_CORE
185 if (field.FieldType.IsValueType())
186#else
187 if (field.FieldType.IsValueType)
188#endif
189 {
190 body = Expression.Convert(body, typeof(object));
191 }
192
193 var lambda = Expression.Lambda<DynamicMemberGetDelegate>(
194 body,
195 target);
196
197 return lambda.Compile();
198 }
199
200 public static DynamicMemberSetDelegate CreateFieldSetter(FieldInfo field)
201 {
202 if (field == null)
203 throw new ArgumentNullException("property");
204
205 var target = Expression.Parameter(typeof(object));
206 var val = Expression.Parameter(typeof(object));
207
208 Expression body = Expression.Assign(
209 Expression.Field(
210 Expression.Convert(target, field.DeclaringType),
211 field),
212 Expression.Convert(val, field.FieldType));
213
214 var lambda = Expression.Lambda<DynamicMemberSetDelegate>(
215 body,
216 target,
217 val);
218
219 return lambda.Compile();
220 }
221
222#if !NETFX_CORE && !IOS && !NETSTANDARD2_0 && !NET5_0
223 private static void EmitCastToReference(ILGenerator il, Type type)
224 {
225 if (type.IsValueType)
226 il.Emit(OpCodes.Unbox_Any, type);
227 else
228 il.Emit(OpCodes.Castclass, type);
229 }
230#endif
231 }
232}
233#endif
A strongly-typed resource class, for looking up localized strings, etc.
static string ConstructorsWithParametersNotSupported
Looks up a localized string similar to Constructor with parameters are not supported.
delegate void DynamicMemberSetDelegate(object target, object arg)
Delegate for setting a value.
delegate object DynamicMethodDelegate(object target, object[] args)
Delegate for a dynamic method.
delegate object DynamicMemberGetDelegate(object target)
Delegate for getting a value.
delegate object DynamicCtorDelegate()
Delegate for a dynamic constructor method.