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> GetConstructorDelegateForType(ClrComplexType clrType)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> GetConstructorDelegateForType(ClrEntityType clrType)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> GetValue(EdmProperty property, object target)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 GetGetterDelegateForProperty(EdmProperty property)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> SetValue(EdmProperty property, object target, object value)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> GetSetterDelegateForProperty(EdmProperty property)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> GetRelatedEnd(RelationshipManager sourceRelationshipManager, AssociationEndMember sourceMember, AssociationEndMember targetMember, RelatedEnd existingRelatedEnd)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 CreateNavigationPropertySetter(Type declaringType, PropertyInfo navigationProperty)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> GetConstructorForType(Type type)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> CreateConstructor(Type type)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> CreatePropertyGetter(RuntimeTypeHandle entityDeclaringType, RuntimeMethodHandle rmh)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 && (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 && (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> CreatePropertySetter(RuntimeTypeHandle entityDeclaringType, RuntimeMethodHandle rmh, bool allowNull)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 ValidateSetterProperty(RuntimeTypeHandle entityDeclaringType, RuntimeMethodHandle setterMethodHandle, out MethodInfo setterMethodInfo, out Type realType)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> RequiresPermissionDemands(MethodBase mi)434 internal static bool RequiresPermissionDemands(MethodBase mi) 435 { 436 System.Diagnostics.Debug.Assert(mi != null); 437 return !IsPublic(mi); 438 } 439 GenerateNecessaryPermissionDemands(ILGenerator gen, MethodBase mi)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 IsPublic(MethodBase method)449 internal static bool IsPublic(MethodBase method) 450 { 451 return (method.IsPublic && IsPublic(method.DeclaringType)); 452 } 453 IsPublic(Type type)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)] CreateGetRelatedEndMethod(AssociationEndMember sourceMember, AssociationEndMember targetMember)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 ThrowConstructorNoParameterless(Type type)527 private static void ThrowConstructorNoParameterless(Type type) 528 { 529 throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_ConstructorNoParameterless(type.FullName)); 530 } ThrowPropertyDeclaringTypeIsValueType()531 private static void ThrowPropertyDeclaringTypeIsValueType() 532 { 533 throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyDeclaringTypeIsValueType); 534 } ThrowPropertyUnsupportedForm()535 private static void ThrowPropertyUnsupportedForm() 536 { 537 throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyUnsupportedForm); 538 } ThrowPropertyUnsupportedType()539 private static void ThrowPropertyUnsupportedType() 540 { 541 throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyUnsupportedType); 542 } ThrowPropertyStrongNameIdentity()543 private static void ThrowPropertyStrongNameIdentity() 544 { 545 throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyStrongNameIdentity); 546 } ThrowPropertyIsIndexed()547 private static void ThrowPropertyIsIndexed() 548 { 549 throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyIsIndexed); 550 } ThrowPropertyIsStatic()551 private static void ThrowPropertyIsStatic() 552 { 553 throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyIsStatic); 554 } ThrowPropertyNoGetter()555 private static void ThrowPropertyNoGetter() 556 { 557 throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.CodeGen_PropertyNoGetter); 558 } ThrowPropertyNoSetter()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 HasMemberAccessReflectionPermission()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)] CreateDynamicMethod(string name, Type returnType, Type[] parameterTypes)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 } 600