Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Metadata / Edm / LightweightCodeGenerator.cs
1 //---------------------------------------------------------------------
2 // <copyright file="LightweightCodeGenerator.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 namespace System.Data.Objects
11 {
12     using System;
13     using System.Data.Common.Utils;
14     using System.Data.Metadata.Edm;
15     using System.Data.Objects.DataClasses;
16     using System.Diagnostics;
17     using System.Reflection;
18     using System.Reflection.Emit;
19     using System.Runtime.CompilerServices;
20     using System.Security;
21     using System.Security.Permissions;
22
23     /// <summary>
24     /// CodeGenerator class: use lightweight code gen to dynamically generate code to get/set properties.
25     /// </summary>
26     internal static class LightweightCodeGenerator
27     {
28         /// <summary>For an OSpace ComplexType returns the delegate to construct the clr instance.</summary>
29         internal static Delegate GetConstructorDelegateForType(ClrComplexType clrType)
30         {
31             return (clrType.Constructor ?? (clrType.Constructor = CreateConstructor(clrType.ClrType)));
32         }
33
34         /// <summary>For an OSpace EntityType returns the delegate to construct the clr instance.</summary>
35         internal static Delegate GetConstructorDelegateForType(ClrEntityType clrType)
36         {
37             return (clrType.Constructor ?? (clrType.Constructor = CreateConstructor(clrType.ClrType)));
38         }
39
40         /// <summary>for an OSpace property, get the property value from a clr instance</summary>
41         internal static object GetValue(EdmProperty property, object target)
42         {
43             Func<object, object> getter = GetGetterDelegateForProperty(property);
44             Debug.Assert(null != getter, "null getter");
45
46             return getter(target);
47         }
48
49         internal static Func<object,object> GetGetterDelegateForProperty(EdmProperty property)
50         {
51             return property.ValueGetter ?? (property.ValueGetter = CreatePropertyGetter(property.EntityDeclaringType, property.PropertyGetterHandle));
52         }
53
54         /// <summary>for an OSpace property, set the property value on a clr instance</summary>
55         /// <exception cref="System.Data.ConstraintException">
56         /// If <paramref name="value"/> is null for a non nullable property.
57         /// </exception>
58         /// <exception cref="System.InvalidOperationException">
59         /// Invalid cast of <paramref name="value"/> to property type.
60         /// </exception>
61         /// <exception cref="System.ArgumentOutOfRangeException">
62         /// From generated enties via StructuralObject.SetValidValue.
63         /// </exception>
64         /// <permission cref="System.Security.Permissions.ReflectionPermission">
65         /// If the property setter is not public or declaring class is not public.
66         /// </permission>
67         /// <permission cref="System.Security.NamedPermissionSet">
68         /// Demand for FullTrust if the property setter or declaring class has a <see cref="System.Security.Permissions.SecurityAction.LinkDemand"/>
69         /// </permission>
70         internal static void SetValue(EdmProperty property, object target, object value)
71         {
72             Action<object, object> setter = GetSetterDelegateForProperty(property);
73             setter(target, value);
74         }
75
76         /// <summary>For an OSpace property, gets the delegate to set the property value on a clr instance.</summary>
77         internal static Action<object, object> GetSetterDelegateForProperty(EdmProperty property)
78         {
79             Action<object, object> setter = property.ValueSetter;
80             if (null == setter)
81             {
82                 setter = CreatePropertySetter(property.EntityDeclaringType, property.PropertySetterHandle,
83                         property.Nullable);
84                 property.ValueSetter = setter;
85             }
86             Debug.Assert(null != setter, "null setter");
87             return setter;
88         }
89
90         /// <summary>
91         /// Gets the related end instance for the source AssociationEndMember by creating a DynamicMethod to 
92         /// call GetRelatedCollection or GetRelatedReference
93         /// </summary>
94         internal static RelatedEnd GetRelatedEnd(RelationshipManager sourceRelationshipManager, AssociationEndMember sourceMember, AssociationEndMember targetMember, RelatedEnd existingRelatedEnd)
95         {
96             Func<RelationshipManager, RelatedEnd, RelatedEnd> getRelatedEnd = sourceMember.GetRelatedEnd;
97             if (null == getRelatedEnd)
98             {
99                 getRelatedEnd = CreateGetRelatedEndMethod(sourceMember, targetMember);
100                 sourceMember.GetRelatedEnd = getRelatedEnd;
101             }
102             Debug.Assert(null != getRelatedEnd, "null getRelatedEnd");
103
104             return getRelatedEnd(sourceRelationshipManager, existingRelatedEnd);
105         }
106
107         #region Navigation Property
108
109         internal static Action<object, object> CreateNavigationPropertySetter(Type declaringType, PropertyInfo navigationProperty)
110         {
111             MethodInfo mi = navigationProperty.GetSetMethod(true);
112             Type realType = navigationProperty.PropertyType;
113
114             if (null == mi)
115             {
116                 ThrowPropertyNoSetter();
117             }
118             if (mi.IsStatic)
119             {
120                 ThrowPropertyIsStatic();
121             }
122             if (mi.DeclaringType.IsValueType)
123             {
124                 ThrowPropertyDeclaringTypeIsValueType();
125             }
126             
127             // the setter always skips visibility so that we can call our internal method to handle errors
128             // because CreateDynamicMethod asserts ReflectionPermission, method is "elevated" and must be treated carefully
129             DynamicMethod method = CreateDynamicMethod(mi.Name, typeof(void), new Type[] { typeof(object), typeof(object) });
130             ILGenerator gen = method.GetILGenerator();
131             GenerateNecessaryPermissionDemands(gen, mi);
132
133             gen.Emit(OpCodes.Ldarg_0);
134             gen.Emit(OpCodes.Castclass, declaringType);
135             gen.Emit(OpCodes.Ldarg_1);
136             gen.Emit(OpCodes.Castclass, navigationProperty.PropertyType);
137             gen.Emit(OpCodes.Callvirt, mi);       // .Property =
138             gen.Emit(OpCodes.Ret);
139
140             return (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
141         }
142
143         #endregion
144
145         #region get the delegate
146
147         /// <summary>Gets a parameterless constructor for the specified type.</summary>
148         /// <param name="type">Type to get constructor for.</param>
149         /// <returns>Parameterless constructor for the specified type.</returns>
150         internal static ConstructorInfo GetConstructorForType(Type type)
151         {
152             System.Diagnostics.Debug.Assert(type != null);
153             ConstructorInfo ci = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, System.Type.EmptyTypes, null);
154             if (null == ci)
155             {
156                 ThrowConstructorNoParameterless(type);
157             }
158             return ci;
159         }
160
161
162         /// <summary>
163         /// generate a delegate equivalent to
164         /// private object Constructor() { return new XClass(); }
165         /// </summary>
166         internal static Delegate CreateConstructor(Type type)
167         {
168             ConstructorInfo ci = GetConstructorForType(type);
169
170             // because CreateDynamicMethod asserts ReflectionPermission, method is "elevated" and must be treated carefully
171             DynamicMethod method = CreateDynamicMethod(ci.DeclaringType.Name, typeof(object), Type.EmptyTypes);
172             ILGenerator gen = method.GetILGenerator();
173             GenerateNecessaryPermissionDemands(gen, ci);
174
175             gen.Emit(OpCodes.Newobj, ci);
176             gen.Emit(OpCodes.Ret);
177             return method.CreateDelegate(typeof(Func<object>));
178         }
179
180         /// <summary>
181         /// generate a delegate equivalent to
182         /// private object MemberGetter(object target) { return target.PropertyX; }
183         /// or if the property is Nullable<> generate a delegate equivalent to
184         /// private object MemberGetter(object target) { Nullable<X> y = target.PropertyX; return ((y.HasValue) ? y.Value : null); }
185         /// </summary>
186         private static Func<object, object> CreatePropertyGetter(RuntimeTypeHandle entityDeclaringType, RuntimeMethodHandle rmh)
187         {
188             if (default(RuntimeMethodHandle).Equals(rmh))
189             {
190                 ThrowPropertyNoGetter();
191             }
192
193             Debug.Assert(!default(RuntimeTypeHandle).Equals(entityDeclaringType), "Type handle of entity should always be known.");
194             var mi = (MethodInfo)MethodBase.GetMethodFromHandle(rmh, entityDeclaringType);
195
196             if (mi.IsStatic)
197             {
198                 ThrowPropertyIsStatic();
199             }
200             if (mi.DeclaringType.IsValueType)
201             {
202                 ThrowPropertyDeclaringTypeIsValueType();
203             }
204
205             if (0 != mi.GetParameters().Length)
206             {
207                 ThrowPropertyIsIndexed();
208             }
209
210             Type realType = mi.ReturnType;
211             if ((null == realType) || (typeof(void) == realType))
212             {
213                 ThrowPropertyUnsupportedForm();
214             }
215             if (realType.IsPointer)
216             {
217                 ThrowPropertyUnsupportedType();
218             }
219
220             // because CreateDynamicMethod asserts ReflectionPermission, method is "elevated" and must be treated carefully
221             DynamicMethod method = CreateDynamicMethod(mi.Name, typeof(object), new Type[] { typeof(object) });
222             ILGenerator gen = method.GetILGenerator();
223             GenerateNecessaryPermissionDemands(gen, mi);
224
225             // the 'this' target pointer
226             gen.Emit(OpCodes.Ldarg_0);
227             gen.Emit(OpCodes.Castclass, mi.DeclaringType);
228             gen.Emit(mi.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, mi);
229
230             if (realType.IsValueType)
231             {
232                 Type elementType;
233                 if (realType.IsGenericType && (typeof(Nullable<>) == realType.GetGenericTypeDefinition()))
234                 {
235                     elementType = realType.GetGenericArguments()[0];
236
237                     Label lableFalse = gen.DefineLabel();
238                     LocalBuilder local = gen.DeclareLocal(realType);
239                     gen.Emit(OpCodes.Stloc_S, local);
240
241                     gen.Emit(OpCodes.Ldloca_S, local);
242                     gen.Emit(OpCodes.Call, realType.GetMethod("get_HasValue"));
243                     gen.Emit(OpCodes.Brfalse_S, lableFalse);
244
245                     gen.Emit(OpCodes.Ldloca_S, local);
246                     gen.Emit(OpCodes.Call, realType.GetMethod("get_Value"));
247                     gen.Emit(OpCodes.Box, elementType = realType.GetGenericArguments()[0]);
248                     gen.Emit(OpCodes.Ret);
249
250                     gen.MarkLabel(lableFalse);
251                     gen.Emit(OpCodes.Ldnull);
252                 }
253                 else
254                 {
255                     // need to box to return value as object
256                     elementType = realType;
257                     gen.Emit(OpCodes.Box, elementType);
258                 }
259             }
260             gen.Emit(OpCodes.Ret);
261             return (Func<object, object>)method.CreateDelegate(typeof(Func<object, object>));
262         }
263
264         /// <summary>
265         /// generate a delegate equivalent to
266         /// 
267         /// // if Property is Nullable value type
268         /// private void MemberSetter(object target, object value) {
269         ///     if (AllwNull &amp;&amp; (null == value)) {
270         ///         ((TargetType)target).PropertyName = default(PropertyType?);
271         ///         return;
272         ///     }
273         ///     if (value is PropertyType) {
274         ///             ((TargetType)target).PropertyName = new (PropertyType?)((PropertyType)value);
275         ///         return;
276         ///     }
277         ///     ThrowInvalidValue(value, TargetType.Name, PropertyName);
278         ///     return
279         /// }
280         /// 
281         /// // when PropertyType is a value type
282         /// private void MemberSetter(object target, object value) {
283         ///     if (value is PropertyType) {
284         ///             ((TargetType)target).PropertyName = (PropertyType)value;
285         ///         return;
286         ///     }
287         ///     ThrowInvalidValue(value, TargetType.Name, PropertyName);
288         ///     return
289         /// } 
290         /// 
291         /// // when PropertyType is a reference type
292         /// private void MemberSetter(object target, object value) {
293         ///     if ((AllwNull &amp;&amp; (null == value)) || (value is PropertyType)) {
294         ///         ((TargetType)target).PropertyName = ((PropertyType)value);
295         ///         return;
296         ///     }
297         ///     ThrowInvalidValue(value, TargetType.Name, PropertyName);
298         ///     return
299         /// }
300         /// </summary>
301         /// <exception cref="System.InvalidOperationException">
302         /// If the method is missing or static or has indexed parameters.
303         /// Or if the delcaring type is a value type.
304         /// Or if the parameter type is a pointer.
305         /// Or if the method or declaring class has a <see cref="System.Security.Permissions.StrongNameIdentityPermissionAttribute"/>.
306         /// </exception>
307         private static Action<object, object> CreatePropertySetter(RuntimeTypeHandle entityDeclaringType, RuntimeMethodHandle rmh, bool allowNull)
308         {
309             MethodInfo mi;
310             Type realType;
311             ValidateSetterProperty(entityDeclaringType, rmh, out mi, out realType);
312
313             // the setter always skips visibility so that we can call our internal method to handle errors
314             // because CreateDynamicMethod asserts ReflectionPermission, method is "elevated" and must be treated carefully
315             DynamicMethod method = CreateDynamicMethod(mi.Name, typeof(void), new Type[] { typeof(object), typeof(object) });
316             ILGenerator gen = method.GetILGenerator();
317             GenerateNecessaryPermissionDemands(gen, mi);
318
319             Type elementType = realType;
320             Label labelContinueNull = gen.DefineLabel();
321             Label labelContinueValue = gen.DefineLabel();
322             Label labelInvalidValue = gen.DefineLabel();
323             if (realType.IsValueType)
324             {
325                 if (realType.IsGenericType && (typeof(Nullable<>) == realType.GetGenericTypeDefinition()))
326                 {
327                     elementType = realType.GetGenericArguments()[0];
328                 }
329                 else
330                 {   // force allowNull false for non-nullable value types
331                     allowNull = false;
332                 }
333             }
334
335             // ((TargetType)instance)
336             gen.Emit(OpCodes.Ldarg_0);
337             gen.Emit(OpCodes.Castclass, mi.DeclaringType);
338
339             // if (value is elementType) {
340             gen.Emit(OpCodes.Ldarg_1);
341             gen.Emit(OpCodes.Isinst, elementType);
342
343             if (allowNull)
344             {   // reference type or nullable type
345                 gen.Emit(OpCodes.Ldarg_1);
346                 if (elementType == realType)
347                 {
348                     gen.Emit(OpCodes.Brfalse_S, labelContinueNull);             // if (null ==
349                 }
350                 else
351                 {
352                     gen.Emit(OpCodes.Brtrue, labelContinueValue);
353                     gen.Emit(OpCodes.Pop);                                      // pop Isinst
354
355                     LocalBuilder local = gen.DeclareLocal(realType);
356                     gen.Emit(OpCodes.Ldloca_S, local);                          // load valuetype&
357                     gen.Emit(OpCodes.Initobj, realType);                        // init &
358                     gen.Emit(OpCodes.Ldloc_0);                                  // load valuetype
359                     gen.Emit(OpCodes.Br_S, labelContinueNull);
360                     gen.MarkLabel(labelContinueValue);
361                 }
362             }
363             gen.Emit(OpCodes.Dup);
364             gen.Emit(OpCodes.Brfalse_S, labelInvalidValue);                     // (arg1 is Inst)
365
366             if (elementType.IsValueType)
367             {
368                 gen.Emit(OpCodes.Unbox_Any, elementType);                       // ((PropertyType)value)
369
370                 if (elementType != realType)
371                 {                                                               // new Nullable<PropertyType>
372                     gen.Emit(OpCodes.Newobj, realType.GetConstructor(new Type[] { elementType }));
373                 }
374             }
375             gen.MarkLabel(labelContinueNull);
376             gen.Emit(mi.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, mi);       // .Property =
377             gen.Emit(OpCodes.Ret);
378
379             // ThrowInvalidValue(value, typeof(PropertyType), DeclaringType.Name, PropertyName
380             gen.MarkLabel(labelInvalidValue);
381             gen.Emit(OpCodes.Pop);                                      // pop Ldarg_0
382             gen.Emit(OpCodes.Pop);                                      // pop IsInst'
383             gen.Emit(OpCodes.Ldarg_1);                                  // determine if InvalidCast or NullReference
384             gen.Emit(OpCodes.Ldtoken, elementType);
385             gen.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Static | BindingFlags.Public));
386             gen.Emit(OpCodes.Ldstr, mi.DeclaringType.Name);
387             gen.Emit(OpCodes.Ldstr, mi.Name.Substring(4)); // substring to strip "set_"
388             Debug.Assert(null != (Action<Object,Type,String,String>)EntityUtil.ThrowSetInvalidValue, "missing method ThrowSetInvalidValue(object,Type,string,string)");
389             gen.Emit(OpCodes.Call, typeof(EntityUtil).GetMethod("ThrowSetInvalidValue", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(object),typeof(Type),typeof(string),typeof(string)},null));
390             gen.Emit(OpCodes.Ret);
391             return (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
392         }
393
394         internal static void ValidateSetterProperty(RuntimeTypeHandle entityDeclaringType, RuntimeMethodHandle setterMethodHandle, out MethodInfo setterMethodInfo, out Type realType)
395         {
396             if (default(RuntimeMethodHandle).Equals(setterMethodHandle))
397             {
398                 ThrowPropertyNoSetter();
399             }
400
401             Debug.Assert(!default(RuntimeTypeHandle).Equals(entityDeclaringType), "Type handle of entity should always be known.");
402             setterMethodInfo = (MethodInfo)MethodBase.GetMethodFromHandle(setterMethodHandle, entityDeclaringType);
403
404             if (setterMethodInfo.IsStatic)
405             {
406                 ThrowPropertyIsStatic();
407             }
408             if (setterMethodInfo.DeclaringType.IsValueType)
409             {
410                 ThrowPropertyDeclaringTypeIsValueType();
411             }
412
413             ParameterInfo[] parameters = setterMethodInfo.GetParameters();
414             if ((null == parameters) || (1 != parameters.Length))
415             {   // if no parameters (i.e. not a set_Property method), will still throw this message
416                 ThrowPropertyIsIndexed();
417             }
418             realType = setterMethodInfo.ReturnType;
419             if ((null != realType) && (typeof(void) != realType))
420             {
421                 ThrowPropertyUnsupportedForm();
422             }
423
424             realType = parameters[0].ParameterType;
425             if (realType.IsPointer)
426             {
427                 ThrowPropertyUnsupportedType();
428             }
429         }
430
431         /// <summary>Determines if the specified method requires permission demands to be invoked safely.</summary>
432         /// <param name="mi">Method instance to check.</param>
433         /// <returns>true if the specified method requires permission demands to be invoked safely, false otherwise.</returns>
434         internal static bool RequiresPermissionDemands(MethodBase mi)
435         {
436             System.Diagnostics.Debug.Assert(mi != null);
437             return !IsPublic(mi);
438         }
439
440         private static void GenerateNecessaryPermissionDemands(ILGenerator gen, MethodBase mi)
441         {
442             if (!IsPublic(mi))
443             {
444                 gen.Emit(OpCodes.Ldsfld, typeof(LightweightCodeGenerator).GetField("MemberAccessReflectionPermission", BindingFlags.Static | BindingFlags.NonPublic));
445                 gen.Emit(OpCodes.Callvirt, typeof(ReflectionPermission).GetMethod("Demand"));
446             }
447         }
448
449         internal static bool IsPublic(MethodBase method)
450         {
451             return (method.IsPublic && IsPublic(method.DeclaringType));
452         }
453
454         internal static bool IsPublic(Type type)
455         {
456             return ((null == type) || (type.IsPublic && IsPublic(type.DeclaringType)));
457         }
458
459         /// <summary>
460         /// Create delegate used to invoke either the GetRelatedReference or GetRelatedCollection generic method on the RelationshipManager.
461         /// </summary>        
462         /// <param name="sourceMember">source end of the relationship for the requested navigation</param>
463         /// <param name="targetMember">target end of the relationship for the requested navigation</param>
464         /// <returns>Delegate that can be used to invoke the corresponding method.</returns>
465         [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
466         private static Func<RelationshipManager, RelatedEnd, RelatedEnd> CreateGetRelatedEndMethod(AssociationEndMember sourceMember, AssociationEndMember targetMember)
467         {
468             Debug.Assert(sourceMember.DeclaringType == targetMember.DeclaringType, "Source and Target members must be in the same DeclaringType");
469
470             EntityType sourceEntityType = MetadataHelper.GetEntityTypeForEnd(sourceMember);
471             EntityType targetEntityType = MetadataHelper.GetEntityTypeForEnd(targetMember);
472             NavigationPropertyAccessor sourceAccessor = MetadataHelper.GetNavigationPropertyAccessor(targetEntityType, targetMember, sourceMember);
473             NavigationPropertyAccessor targetAccessor = MetadataHelper.GetNavigationPropertyAccessor(sourceEntityType, sourceMember, targetMember);
474
475             MethodInfo genericCreateRelatedEndMethod = typeof(LightweightCodeGenerator).GetMethod("CreateGetRelatedEndMethod", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(AssociationEndMember), typeof(AssociationEndMember), typeof(NavigationPropertyAccessor), typeof(NavigationPropertyAccessor) }, null);
476             Debug.Assert(genericCreateRelatedEndMethod != null, "Could not find method LightweightCodeGenerator.CreateGetRelatedEndMethod");
477
478             MethodInfo createRelatedEndMethod = genericCreateRelatedEndMethod.MakeGenericMethod(sourceEntityType.ClrType, targetEntityType.ClrType);
479             object getRelatedEndDelegate = createRelatedEndMethod.Invoke(null, new object[] { sourceMember, targetMember, sourceAccessor, targetAccessor });
480
481             return (Func<RelationshipManager, RelatedEnd, RelatedEnd>)getRelatedEndDelegate;
482         }
483
484         private static Func<RelationshipManager, RelatedEnd, RelatedEnd> CreateGetRelatedEndMethod<TSource, TTarget>(AssociationEndMember sourceMember, AssociationEndMember targetMember, NavigationPropertyAccessor sourceAccessor, NavigationPropertyAccessor targetAccessor)
485             where TSource : class
486             where TTarget : class
487         {
488             Func<RelationshipManager, RelatedEnd, RelatedEnd> getRelatedEnd;
489
490             // Get the appropriate method, either collection or reference depending on the target multiplicity
491             switch (targetMember.RelationshipMultiplicity)
492             {
493                 case RelationshipMultiplicity.ZeroOrOne:
494                 case RelationshipMultiplicity.One:
495                     {
496                         getRelatedEnd = (manager, relatedEnd) =>
497                             manager.GetRelatedReference<TSource, TTarget>(sourceMember.DeclaringType.FullName,
498                                                                           sourceMember.Name,
499                                                                           targetMember.Name,
500                                                                           sourceAccessor,
501                                                                           targetAccessor,
502                                                                           sourceMember.RelationshipMultiplicity,
503                                                                           relatedEnd);
504                         
505                         break;
506                     }
507                 case RelationshipMultiplicity.Many:
508                     {
509                         getRelatedEnd = (manager, relatedEnd) =>
510                             manager.GetRelatedCollection<TSource, TTarget>(sourceMember.DeclaringType.FullName,
511                                                                            sourceMember.Name,
512                                                                            targetMember.Name,
513                                                                            sourceAccessor,
514                                                                            targetAccessor,
515                                                                            sourceMember.RelationshipMultiplicity,
516                                                                            relatedEnd);
517
518                         break;
519                     }
520                 default:
521                     throw EntityUtil.InvalidEnumerationValue(typeof(RelationshipMultiplicity), (int)targetMember.RelationshipMultiplicity);
522             }
523
524             return getRelatedEnd;
525         }
526
527         private static void ThrowConstructorNoParameterless(Type type)
528         {
529             throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_ConstructorNoParameterless(type.FullName));
530         }
531         private static void ThrowPropertyDeclaringTypeIsValueType()
532         {
533             throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyDeclaringTypeIsValueType);
534         }
535         private static void ThrowPropertyUnsupportedForm()
536         {
537             throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyUnsupportedForm);
538         }
539         private static void ThrowPropertyUnsupportedType()
540         {
541             throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyUnsupportedType);
542         }
543         private static void ThrowPropertyStrongNameIdentity()
544         {
545             throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyStrongNameIdentity);
546         }
547         private static void ThrowPropertyIsIndexed()
548         {
549             throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyIsIndexed);
550         }
551         private static void ThrowPropertyIsStatic()
552         {
553             throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyIsStatic);
554         }
555         private static void ThrowPropertyNoGetter()
556         {
557             throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyNoGetter);
558         }
559         private static void ThrowPropertyNoSetter()
560         {
561             throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyNoSetter);
562         }
563
564         #endregion
565
566         #region Lightweight code generation
567
568         internal static readonly ReflectionPermission MemberAccessReflectionPermission = new ReflectionPermission(ReflectionPermissionFlag.MemberAccess);
569
570         internal static bool HasMemberAccessReflectionPermission()
571         {
572             try
573             {
574                 MemberAccessReflectionPermission.Demand();
575                 return true;
576             }
577             catch (SecurityException)
578             {
579                 return false;
580             }
581         }
582
583         // we could cache more, like 'new Type[] { ... }' and 'typeof(object)'
584         // but pruned as much as possible for the workingset helps, even little things
585
586         // Assert MemberAccess to skip visibility check & ReflectionEmit so we can generate the method (make calls to EF internals).
587         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2128")]
588         [System.Security.SecuritySafeCritical]
589         [ReflectionPermission(SecurityAction.Assert, MemberAccess = true)]
590         internal static DynamicMethod CreateDynamicMethod(string name, Type returnType, Type[] parameterTypes)
591         {
592             // Create a transparent dynamic method (Module not specified) to ensure we do not satisfy any link demands
593             // in method callees.
594             return new DynamicMethod(name, returnType, parameterTypes, true);
595         }
596
597         #endregion
598     }
599 }