/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public static bool TryGetMemberInfo( [NotNull] this IPropertyBase propertyBase, bool forConstruction, bool forSet, out MemberInfo memberInfo, out string errorMessage) { memberInfo = null; errorMessage = null; var propertyInfo = propertyBase.PropertyInfo; var fieldInfo = propertyBase.FieldInfo; var setterProperty = propertyInfo?.FindSetterProperty(); var getterProperty = propertyInfo?.FindGetterProperty(); var isCollectionNav = (propertyBase as INavigation)?.IsCollection() == true; var hasField = fieldInfo != null; var hasSetter = setterProperty != null; var hasGetter = getterProperty != null; var mode = propertyBase.GetPropertyAccessMode(); if (forConstruction) { if (mode == PropertyAccessMode.Field || mode == PropertyAccessMode.FieldDuringConstruction) { if (hasField) { memberInfo = fieldInfo; return(true); } if (isCollectionNav) { return(true); } errorMessage = GetNoFieldErrorMessage(propertyBase); return(false); } if (mode == PropertyAccessMode.Property) { if (hasSetter) { memberInfo = setterProperty; return(true); } if (isCollectionNav) { return(true); } errorMessage = hasGetter ? CoreStrings.NoSetter(propertyBase.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)) : CoreStrings.NoProperty(fieldInfo?.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)); return(false); } if (mode == PropertyAccessMode.PreferField || mode == PropertyAccessMode.PreferFieldDuringConstruction) { if (hasField) { memberInfo = fieldInfo; return(true); } if (hasSetter) { memberInfo = setterProperty; return(true); } } if (mode == PropertyAccessMode.PreferProperty) { if (hasSetter) { memberInfo = setterProperty; return(true); } if (hasField) { memberInfo = fieldInfo; return(true); } } if (isCollectionNav) { return(true); } errorMessage = CoreStrings.NoFieldOrSetter(propertyBase.Name, propertyBase.DeclaringType.DisplayName()); return(false); } if (forSet) { if (mode == PropertyAccessMode.Field) { if (hasField) { memberInfo = fieldInfo; return(true); } if (isCollectionNav) { return(true); } errorMessage = GetNoFieldErrorMessage(propertyBase); return(false); } if (mode == PropertyAccessMode.Property) { if (hasSetter) { memberInfo = setterProperty; return(true); } if (isCollectionNav) { return(true); } errorMessage = hasGetter ? CoreStrings.NoSetter(propertyBase.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)) : CoreStrings.NoProperty(fieldInfo?.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)); return(false); } if (mode == PropertyAccessMode.PreferField) { if (hasField) { memberInfo = fieldInfo; return(true); } if (hasSetter) { memberInfo = setterProperty; return(true); } } if (mode == PropertyAccessMode.PreferProperty || mode == PropertyAccessMode.FieldDuringConstruction || mode == PropertyAccessMode.PreferFieldDuringConstruction) { if (hasSetter) { memberInfo = setterProperty; return(true); } if (hasField) { memberInfo = fieldInfo; return(true); } } if (isCollectionNav) { return(true); } errorMessage = CoreStrings.NoFieldOrSetter(propertyBase.Name, propertyBase.DeclaringType.DisplayName()); return(false); } // forGet if (mode == PropertyAccessMode.Field) { if (hasField) { memberInfo = fieldInfo; return(true); } errorMessage = GetNoFieldErrorMessage(propertyBase); return(false); } if (mode == PropertyAccessMode.Property) { if (hasGetter) { memberInfo = getterProperty; return(true); } errorMessage = hasSetter ? CoreStrings.NoGetter(propertyBase.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)) : CoreStrings.NoProperty(fieldInfo?.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)); return(false); } if (mode == PropertyAccessMode.PreferField) { if (hasField) { memberInfo = fieldInfo; return(true); } if (hasGetter) { memberInfo = getterProperty; return(true); } } if (mode == PropertyAccessMode.PreferProperty || mode == PropertyAccessMode.FieldDuringConstruction || mode == PropertyAccessMode.PreferFieldDuringConstruction) { if (hasGetter) { memberInfo = getterProperty; return(true); } if (hasField) { memberInfo = fieldInfo; return(true); } } errorMessage = CoreStrings.NoFieldOrGetter(propertyBase.Name, propertyBase.DeclaringType.DisplayName()); return(false); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public static bool TryGetMemberInfo( [NotNull] this IPropertyBase propertyBase, bool forConstruction, bool forSet, [CanBeNull] out MemberInfo memberInfo, [CanBeNull] out string errorMessage) { memberInfo = null; errorMessage = null; var propertyInfo = propertyBase.PropertyInfo; var fieldInfo = propertyBase.FieldInfo; var isCollectionNav = (propertyBase as INavigation)?.IsCollection() == true; var mode = propertyBase.GetPropertyAccessMode(); if (mode == null || mode == PropertyAccessMode.FieldDuringConstruction) { if (forConstruction && fieldInfo != null && !fieldInfo.IsInitOnly) { memberInfo = fieldInfo; return(true); } if (forConstruction) { if (fieldInfo != null) { if (!fieldInfo.IsInitOnly) { memberInfo = fieldInfo; return(true); } if (mode == PropertyAccessMode.FieldDuringConstruction && !isCollectionNav) { errorMessage = CoreStrings.ReadonlyField(fieldInfo.Name, propertyBase.DeclaringType.DisplayName()); return(false); } } if (mode == PropertyAccessMode.FieldDuringConstruction) { if (!isCollectionNav) { errorMessage = CoreStrings.NoBackingField( propertyBase.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)); return(false); } return(true); } } if (forSet) { var setterProperty = propertyInfo?.FindSetterProperty(); if (setterProperty != null) { memberInfo = setterProperty; return(true); } if (fieldInfo != null) { if (!fieldInfo.IsInitOnly) { memberInfo = fieldInfo; return(true); } if (!isCollectionNav) { errorMessage = CoreStrings.ReadonlyField(fieldInfo.Name, propertyBase.DeclaringType.DisplayName()); return(false); } } if (!isCollectionNav) { errorMessage = CoreStrings.NoFieldOrSetter(propertyBase.Name, propertyBase.DeclaringType.DisplayName()); return(false); } return(true); } var getterPropertyInfo = propertyInfo?.FindGetterProperty(); if (getterPropertyInfo != null) { memberInfo = getterPropertyInfo; return(true); } if (fieldInfo != null) { memberInfo = fieldInfo; return(true); } errorMessage = CoreStrings.NoFieldOrGetter(propertyBase.Name, propertyBase.DeclaringType.DisplayName()); return(false); } if (mode == PropertyAccessMode.Field) { if (fieldInfo == null) { if (!forSet || !isCollectionNav) { errorMessage = CoreStrings.NoBackingField( propertyBase.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)); return(false); } return(true); } if (forSet && fieldInfo.IsInitOnly) { if (!isCollectionNav) { errorMessage = CoreStrings.ReadonlyField(fieldInfo.Name, propertyBase.DeclaringType.DisplayName()); return(false); } return(true); } memberInfo = fieldInfo; return(true); } if (propertyInfo == null) { errorMessage = CoreStrings.NoProperty(fieldInfo.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)); return(false); } if (forSet) { var setterProperty = propertyInfo.FindSetterProperty(); if (setterProperty == null && !isCollectionNav) { errorMessage = CoreStrings.NoSetter(propertyBase.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)); return(false); } memberInfo = setterProperty; return(true); } var getterProperty = propertyInfo.FindGetterProperty(); if (getterProperty == null) { errorMessage = CoreStrings.NoGetter(propertyBase.Name, propertyBase.DeclaringType.DisplayName(), nameof(PropertyAccessMode)); return(false); } memberInfo = getterProperty; return(true); }