diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs index e54c136be43..868f877b5c3 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs @@ -13,10 +13,8 @@ using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Conventions; -using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage; using Newtonsoft.Json.Linq; @@ -520,11 +518,11 @@ private static void IncludeCollection( } private static void SetIsLoadedNoTracking(object entity, INavigation navigation) - => ((ILazyLoader)((PropertyBase)navigation + => ((ILazyLoader)(navigation .DeclaringEntityType .GetServiceProperties() .FirstOrDefault(p => p.ClrType == typeof(ILazyLoader))) - ?.Getter.GetClrValue(entity)) + ?.GetGetter().GetClrValue(entity)) ?.SetLoaded(entity, navigation.Name); private static LambdaExpression GenerateFixup( @@ -558,8 +556,7 @@ private static Expression AssignReferenceNavigation( ParameterExpression entity, ParameterExpression relatedEntity, INavigation navigation) - => entity.MakeMemberAccess(navigation.GetMemberInfo(forConstruction: false, forSet: true)) - .CreateAssignExpression(relatedEntity); + => entity.MakeMemberAccess(navigation.GetMemberInfo(forMaterialization: false, forSet: true)).Assign(relatedEntity); private static Expression AddToCollectionNavigation( ParameterExpression entity, diff --git a/src/EFCore.Relational/Query/Internal/IncludeCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/IncludeCompilingExpressionVisitor.cs similarity index 98% rename from src/EFCore.Relational/Query/Internal/IncludeCompilingExpressionVisitor.cs rename to src/EFCore.Relational/Query/IncludeCompilingExpressionVisitor.cs index 093e65f716a..35d3b152095 100644 --- a/src/EFCore.Relational/Query/Internal/IncludeCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/IncludeCompilingExpressionVisitor.cs @@ -10,10 +10,7 @@ using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Query.NavigationExpansion.Internal; namespace Microsoft.EntityFrameworkCore.Query { @@ -275,11 +272,11 @@ private static TCollection InitializeCollection( } private static void SetIsLoadedNoTracking(object entity, INavigation navigation) - => ((ILazyLoader)((PropertyBase)navigation + => ((ILazyLoader)(navigation .DeclaringEntityType .GetServiceProperties() .FirstOrDefault(p => p.ClrType == typeof(ILazyLoader))) - ?.Getter.GetClrValue(entity)) + ?.GetGetter().GetClrValue(entity)) ?.SetLoaded(entity, navigation.Name); protected override Expression VisitExtension(Expression extensionExpression) @@ -469,8 +466,7 @@ private static Expression AssignReferenceNavigation( ParameterExpression relatedEntity, INavigation navigation) { - return entity.MakeMemberAccess(navigation.GetMemberInfo(forConstruction: true, forSet: true)) - .CreateAssignExpression(relatedEntity); + return entity.MakeMemberAccess(navigation.GetMemberInfo(forMaterialization: true, forSet: true)).Assign(relatedEntity); } private static Expression AddToCollectionNavigation( diff --git a/src/EFCore.Relational/Query/RelationalProjectionBindingRemovingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalProjectionBindingRemovingExpressionVisitor.cs index 69b2f1300ab..aed899ceeda 100644 --- a/src/EFCore.Relational/Query/RelationalProjectionBindingRemovingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalProjectionBindingRemovingExpressionVisitor.cs @@ -7,9 +7,8 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; diff --git a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs index 1a14c9ade6b..a4901a8e542 100644 --- a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs @@ -136,7 +136,7 @@ private Expression CreateSnapshotExpression( var memberAccess = (Expression)Expression.MakeMemberAccess( entityVariable, - propertyBase.GetMemberInfo(forConstruction: false, forSet: false)); + propertyBase.GetMemberInfo(forMaterialization: false, forSet: false)); if (memberAccess.Type != propertyBase.ClrType) { diff --git a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs index dc2090e61d8..3ae1b380027 100644 --- a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs +++ b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs @@ -207,54 +207,6 @@ public static bool IsEntityQueryable([NotNull] this ConstantExpression constantE => constantExpression.Type.GetTypeInfo().IsGenericType && constantExpression.Type.GetGenericTypeDefinition() == typeof(EntityQueryable<>); - /// - /// 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. - /// - public static MemberExpression MakeMemberAccess( - [CanBeNull] this Expression expression, - [NotNull] MemberInfo member) - { - var memberDeclaringClrType = member.DeclaringType; - if (expression != null - && memberDeclaringClrType != expression.Type - && expression.Type.GetTypeInfo().IsAssignableFrom(memberDeclaringClrType.GetTypeInfo())) - { - expression = Expression.Convert(expression, memberDeclaringClrType); - } - - return Expression.MakeMemberAccess(expression, member); - } - - /// - /// 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. - /// - public static Expression Assign( - [NotNull] this MemberExpression memberExpression, - [NotNull] Expression valueExpression) - { - if (memberExpression.Member is FieldInfo fieldInfo - && fieldInfo.IsInitOnly) - { - return (BinaryExpression)Activator.CreateInstance( - _assignBinaryExpressionType, - BindingFlags.NonPublic | BindingFlags.Instance, - null, - new object[] { memberExpression, valueExpression }, - null); - } - - return Expression.Assign(memberExpression, valueExpression); - } - - private static readonly Type _assignBinaryExpressionType - = typeof(Expression).Assembly.GetType("System.Linq.Expressions.AssignBinaryExpression"); - /// /// 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 diff --git a/src/EFCore/Extensions/NavigationExtensions.cs b/src/EFCore/Extensions/NavigationExtensions.cs index ee899a75ae6..ff59346c308 100644 --- a/src/EFCore/Extensions/NavigationExtensions.cs +++ b/src/EFCore/Extensions/NavigationExtensions.cs @@ -15,6 +15,15 @@ namespace Microsoft.EntityFrameworkCore /// public static class NavigationExtensions { + /// + /// Gets the for this navigation property, which must be a collection + /// navigation. + /// + /// The navigation property. + /// The accessor. + public static IClrCollectionAccessor GetCollectionAccessor([NotNull] this INavigation navigation) + => navigation.AsNavigation().CollectionAccessor; + /// /// Gets a value indicating whether the given navigation property is the navigation property on the dependent entity /// type that points to the principal entity. diff --git a/src/EFCore/Extensions/PropertyBaseExtensions.cs b/src/EFCore/Extensions/PropertyBaseExtensions.cs index db9b11c9699..65be2f4678c 100644 --- a/src/EFCore/Extensions/PropertyBaseExtensions.cs +++ b/src/EFCore/Extensions/PropertyBaseExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Reflection; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.ChangeTracking; @@ -16,6 +17,79 @@ namespace Microsoft.EntityFrameworkCore /// public static class PropertyBaseExtensions { + /// + /// + /// Gets the or that should be used to + /// get or set a value for the given property. + /// + /// + /// Note that it is an error to call this method for a shadow property () since + /// such a property has no associated . + /// + /// + /// The property. + /// If true, then the member to use for query materialization will be returned. + /// + /// If true, then the member to use for setting the property value will be returned, otherwise + /// the member to use for getting the property value will be returned. + /// + /// The to use. + public static MemberInfo GetMemberInfo( + [NotNull] this IPropertyBase propertyBase, + bool forMaterialization, + bool forSet) + { + if (propertyBase.TryGetMemberInfo(forMaterialization, forSet, out var memberInfo, out var errorMessage)) + { + return memberInfo; + } + + throw new InvalidOperationException(errorMessage); + } + + /// + /// + /// Gets a for reading the value of this property. + /// + /// + /// Note that it is an error to call this method for a shadow property () since + /// such a property has no associated . + /// + /// + /// The property. + /// The accessor. + public static IClrPropertyGetter GetGetter([NotNull] this IPropertyBase propertyBase) + => propertyBase.AsPropertyBase().Getter; + + /// + /// + /// Gets a for writing the value of this property. + /// + /// + /// Note that it is an error to call this method for a shadow property () since + /// such a property has no associated . + /// + /// + /// The property. + /// The accessor. + public static IClrPropertySetter GetSetter([NotNull] this IPropertyBase propertyBase) + => propertyBase.AsPropertyBase().Setter; + + /// + /// + /// Gets a for writing the value of this property during materialization + /// of a query. + /// + /// + /// Note that it is an error to call this method for a shadow property () since + /// such a property has no associated . + /// + /// + /// The property. + /// The accessor. + public static IClrPropertySetter GetMaterializationSetter([NotNull] this IPropertyBase propertyBase) + => propertyBase.AsPropertyBase().MaterializationSetter; + /// /// Gets the name of the backing field for this property, or null if the backing field /// is not known. diff --git a/src/EFCore/Infrastructure/ExpressionExtensions.cs b/src/EFCore/Infrastructure/ExpressionExtensions.cs index 459db742ee0..185edf2fe8a 100644 --- a/src/EFCore/Infrastructure/ExpressionExtensions.cs +++ b/src/EFCore/Infrastructure/ExpressionExtensions.cs @@ -16,7 +16,7 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure { /// /// - /// Extension methods for types. + /// Extension methods for types. /// /// /// This type is typically used by database providers (and other extensions). It is generally @@ -25,9 +25,74 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// public static class ExpressionExtensions { + /// + /// Checks whether or not the given represents a call + /// to the method. + /// + /// The method-call expression. + /// True if it is a call to ; false otherwise. public static bool IsEFProperty([NotNull] this MethodCallExpression methodCallExpression) => methodCallExpression.Method.IsEFPropertyMethod(); + /// + /// Creates a that represents accessing either a field or a property. + /// + /// An that represents the object that the member belongs to. + /// The that describes the field or property to be accessed. + /// The that results from calling the appropriate factory method. + public static MemberExpression MakeMemberAccess( + [CanBeNull] this Expression expression, + [NotNull] MemberInfo member) + { + var memberDeclaringClrType = member.DeclaringType; + if (expression != null + && memberDeclaringClrType != expression.Type + && expression.Type.GetTypeInfo().IsAssignableFrom(memberDeclaringClrType.GetTypeInfo())) + { + expression = Expression.Convert(expression, memberDeclaringClrType); + } + + return Expression.MakeMemberAccess(expression, member); + } + + /// + /// Creates a that represents an assignment operation. + /// + /// The member to which assignment will be made. + /// The value that will be assigned. + /// The representing the assignment binding. + public static Expression Assign( + [NotNull] this MemberExpression memberExpression, + [NotNull] Expression valueExpression) + { + if (memberExpression.Member is FieldInfo fieldInfo + && fieldInfo.IsInitOnly) + { + return (BinaryExpression)Activator.CreateInstance( + _assignBinaryExpressionType, + BindingFlags.NonPublic | BindingFlags.Instance, + null, + new object[] + { + memberExpression, valueExpression + }, + null); + } + + return Expression.Assign(memberExpression, valueExpression); + } + + private static readonly Type _assignBinaryExpressionType + = typeof(Expression).Assembly.GetType("System.Linq.Expressions.AssignBinaryExpression"); + + /// + /// If the given a method-call expression represents a call to , then this + /// method extracts the entity expression and property name. + /// + /// The method-call expression for + /// The extracted entity access expression. + /// The accessed property name. + /// True if the method-call was for ; false otherwise. public static bool TryGetEFPropertyArguments( [NotNull] this MethodCallExpression methodCallExpression, out Expression entityExpression, @@ -45,20 +110,16 @@ public static bool TryGetEFPropertyArguments( return false; } - public static Expression CreateAssignExpression( - [NotNull] this MemberExpression left, - [NotNull] Expression right) - { - var leftType = left.Type; - if (leftType != right.Type - && right.Type.GetTypeInfo().IsAssignableFrom(leftType.GetTypeInfo())) - { - right = Expression.Convert(right, leftType); - } - - return left.Assign(right); - } - + /// + /// + /// Gets the represented by a simple property-access expression. + /// + /// + /// This method is typically used to parse property access lambdas from fluent APIs. + /// + /// + /// The expression. + /// The . public static PropertyInfo GetPropertyAccess([NotNull] this LambdaExpression propertyAccessExpression) { Debug.Assert(propertyAccessExpression.Parameters.Count == 1); @@ -99,8 +160,8 @@ public static PropertyInfo GetPropertyAccess([NotNull] this LambdaExpression pro /// /// - /// Returns a list of extracted from the given simple - /// . + /// Returns a list of extracted from the given simple + /// . /// /// /// Only simple expressions are supported, such as those used to reference a property. @@ -140,8 +201,8 @@ var propertyPaths /// /// - /// Returns a new expression with any see or - /// nodes removed from the head of the + /// Returns a new expression with any see or + /// nodes removed from the head of the /// given expression tree/ /// /// diff --git a/src/EFCore/Internal/DbSetProperty.cs b/src/EFCore/Internal/DbSetProperty.cs index 30e3f3a1a70..06a4f8be786 100644 --- a/src/EFCore/Internal/DbSetProperty.cs +++ b/src/EFCore/Internal/DbSetProperty.cs @@ -3,6 +3,7 @@ using System; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Internal diff --git a/src/EFCore/Metadata/IClrCollectionAccessor.cs b/src/EFCore/Metadata/IClrCollectionAccessor.cs new file mode 100644 index 00000000000..aab15418bff --- /dev/null +++ b/src/EFCore/Metadata/IClrCollectionAccessor.cs @@ -0,0 +1,60 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Metadata +{ + /// + /// Represents operations backed by compiled delegates that allow manipulation of collections + /// on navigation properties. + /// + public interface IClrCollectionAccessor + { + /// + /// Adds a value to the navigation property collection, unless it is already contained in the collection. + /// + /// The entity instance. + /// The value to add. + /// If true, then the value is being added as part of query materialization. + /// True if a value was added; false if it was already in the collection. + bool Add([NotNull] object entity, [NotNull] object value, bool forMaterialization); + + /// + /// Checks whether the value is contained in the collection. + /// + /// The entity instance. + /// The value to check. + /// True if the value is contained in the collection; false otherwise. + bool Contains([NotNull] object entity, [NotNull] object value); + + /// + /// Removes a value from the collection. + /// + /// The entity instance. + /// The value to check. + /// True if the value was contained in the collection; false otherwise. + bool Remove([NotNull] object entity, [NotNull] object value); + + /// + /// Creates a new collection instance of the appropriate type for the navigation property. + /// + /// The collection instance. + object Create(); + + /// + /// Either returns the existing collection instance set on the navigation property, or if none + /// exists, then creates a new instance, sets it, and returns it. + /// + /// The entity instance. + /// If true, then this is happening as part of query materialization; false otherwise. + /// The existing or new collection. + object GetOrCreate([NotNull] object entity, bool forMaterialization); + + /// + /// The collection type. + /// + Type CollectionType { get; } + } +} diff --git a/src/EFCore/Metadata/IClrPropertyGetter.cs b/src/EFCore/Metadata/IClrPropertyGetter.cs new file mode 100644 index 00000000000..c80d530e9c3 --- /dev/null +++ b/src/EFCore/Metadata/IClrPropertyGetter.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Metadata +{ + /// + /// Represents operations backed by compiled delegates that support getting the value + /// of a mapped EF property. + /// + public interface IClrPropertyGetter + { + /// + /// Gets the property value. + /// + /// The entity instance. + /// The property value. + object GetClrValue([NotNull] object entity); + + /// + /// Checks whether or not the property is set to the CLR default for its type. + /// + /// The entity instance. + /// True if the property value is the CLR default; false it is any other value. + bool HasDefaultValue([NotNull] object entity); + } +} diff --git a/src/EFCore/Metadata/IClrPropertySetter.cs b/src/EFCore/Metadata/IClrPropertySetter.cs new file mode 100644 index 00000000000..6c3293675a7 --- /dev/null +++ b/src/EFCore/Metadata/IClrPropertySetter.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using JetBrains.Annotations; + +namespace Microsoft.EntityFrameworkCore.Metadata +{ + /// + /// Represents operations backed by compiled delegates that support setting the value + /// of a mapped EF property. + /// + public interface IClrPropertySetter + { + /// + /// Sets the value of the property. + /// + /// The entity instance. + /// The value to set. + void SetClrValue([NotNull] object instance, [CanBeNull] object value); + } +} diff --git a/src/EFCore/Metadata/Internal/ClrCollectionAccessor.cs b/src/EFCore/Metadata/Internal/ClrCollectionAccessor.cs index b3d80cf5895..7adb42ba0cb 100644 --- a/src/EFCore/Metadata/Internal/ClrCollectionAccessor.cs +++ b/src/EFCore/Metadata/Internal/ClrCollectionAccessor.cs @@ -64,9 +64,9 @@ public ClrICollectionAccessor( /// 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. /// - public virtual bool Add(object instance, object value, bool forMaterialization) + public virtual bool Add(object entity, object value, bool forMaterialization) { - var collection = GetOrCreateCollection(instance, forMaterialization); + var collection = GetOrCreateCollection(entity, forMaterialization); var element = (TElement)value; if (!Contains(collection, value)) @@ -103,8 +103,8 @@ public virtual object Create() /// 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. /// - public virtual object GetOrCreate(object instance, bool forMaterialization) - => GetOrCreateCollection(instance, forMaterialization); + public virtual object GetOrCreate(object entity, bool forMaterialization) + => GetOrCreateCollection(entity, forMaterialization); private ICollection GetOrCreateCollection(object instance, bool forMaterialization) { @@ -159,8 +159,8 @@ private ICollection GetCollection(object instance) /// 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. /// - public virtual bool Contains(object instance, object value) - => Contains(GetCollection((TEntity)instance), value); + public virtual bool Contains(object entity, object value) + => Contains(GetCollection((TEntity)entity), value); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -168,9 +168,9 @@ public virtual bool Contains(object instance, object value) /// 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. /// - public virtual bool Remove(object instance, object value) + public virtual bool Remove(object entity, object value) { - var collection = GetCollection((TEntity)instance); + var collection = GetCollection((TEntity)entity); switch (collection) { diff --git a/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs b/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs index 7aceb24f66e..77ba642fca8 100644 --- a/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs +++ b/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs @@ -133,9 +133,9 @@ Action CreateSetterDelegate( var entityParameter = Expression.Parameter(typeof(TEntity), "entity"); var valueParameter = Expression.Parameter(typeof(TCollection), "collection"); - var memberInfoForRead = navigation.GetMemberInfo(forConstruction: false, forSet: false); - var memberInfoForWrite = navigation.GetMemberInfo(forConstruction: false, forSet: true); - var memberInfoForMaterialization = navigation.GetMemberInfo(forConstruction: true, forSet: true); + var memberInfoForRead = navigation.GetMemberInfo(forMaterialization: false, forSet: false); + var memberInfoForWrite = navigation.GetMemberInfo(forMaterialization: false, forSet: true); + var memberInfoForMaterialization = navigation.GetMemberInfo(forMaterialization: true, forSet: true); var memberAccessForRead = (Expression)Expression.MakeMemberAccess(entityParameter, memberInfoForRead); if (memberAccessForRead.Type != typeof(TCollection)) diff --git a/src/EFCore/Metadata/Internal/ClrPropertyGetter.cs b/src/EFCore/Metadata/Internal/ClrPropertyGetter.cs index e3815fd7808..0092608d364 100644 --- a/src/EFCore/Metadata/Internal/ClrPropertyGetter.cs +++ b/src/EFCore/Metadata/Internal/ClrPropertyGetter.cs @@ -38,7 +38,7 @@ public ClrPropertyGetter([NotNull] Func getter, [NotNull] Func< /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public object GetClrValue(object instance) => _getter((TEntity)instance); + public object GetClrValue(object entity) => _getter((TEntity)entity); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -47,6 +47,6 @@ public ClrPropertyGetter([NotNull] Func getter, [NotNull] Func< /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool HasDefaultValue(object instance) => _hasDefaultValue((TEntity)instance); + public bool HasDefaultValue(object entity) => _hasDefaultValue((TEntity)entity); } } diff --git a/src/EFCore/Metadata/Internal/ClrPropertyGetterFactory.cs b/src/EFCore/Metadata/Internal/ClrPropertyGetterFactory.cs index ad1d17eae9c..967fea416cd 100644 --- a/src/EFCore/Metadata/Internal/ClrPropertyGetterFactory.cs +++ b/src/EFCore/Metadata/Internal/ClrPropertyGetterFactory.cs @@ -26,7 +26,7 @@ public class ClrPropertyGetterFactory : ClrAccessorFactory /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public override IClrPropertyGetter Create(IPropertyBase property) - => property as IClrPropertyGetter ?? Create(property.GetMemberInfo(forConstruction: false, forSet: false), property); + => property as IClrPropertyGetter ?? Create(property.GetMemberInfo(forMaterialization: false, forSet: false), property); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Metadata/Internal/ClrPropertyMaterializationSetterFactory.cs b/src/EFCore/Metadata/Internal/ClrPropertyMaterializationSetterFactory.cs index c0f9914948e..9eab89c601b 100644 --- a/src/EFCore/Metadata/Internal/ClrPropertyMaterializationSetterFactory.cs +++ b/src/EFCore/Metadata/Internal/ClrPropertyMaterializationSetterFactory.cs @@ -18,6 +18,6 @@ public class ClrPropertyMaterializationSetterFactory : ClrPropertySetterFactory /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public override IClrPropertySetter Create(IPropertyBase property) - => property as IClrPropertySetter ?? Create(property.GetMemberInfo(forConstruction: true, forSet: true), property); + => property as IClrPropertySetter ?? Create(property.GetMemberInfo(forMaterialization: true, forSet: true), property); } } diff --git a/src/EFCore/Metadata/Internal/ClrPropertySetterFactory.cs b/src/EFCore/Metadata/Internal/ClrPropertySetterFactory.cs index 46ee7a4c8a0..37918417ef1 100644 --- a/src/EFCore/Metadata/Internal/ClrPropertySetterFactory.cs +++ b/src/EFCore/Metadata/Internal/ClrPropertySetterFactory.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace Microsoft.EntityFrameworkCore.Metadata.Internal { @@ -24,7 +24,7 @@ public class ClrPropertySetterFactory : ClrAccessorFactory /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public override IClrPropertySetter Create(IPropertyBase property) - => property as IClrPropertySetter ?? Create(property.GetMemberInfo(forConstruction: false, forSet: true), property); + => property as IClrPropertySetter ?? Create(property.GetMemberInfo(forMaterialization: false, forSet: true), property); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Metadata/Internal/IClrCollectionAccessor.cs b/src/EFCore/Metadata/Internal/IClrCollectionAccessor.cs deleted file mode 100644 index 9a3b47b09bc..00000000000 --- a/src/EFCore/Metadata/Internal/IClrCollectionAccessor.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using JetBrains.Annotations; - -namespace Microsoft.EntityFrameworkCore.Metadata.Internal -{ - /// - /// 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. - /// - public interface IClrCollectionAccessor - { - /// - /// 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. - /// - bool Add([NotNull] object instance, [NotNull] object value, bool forMaterialization); - - /// - /// 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. - /// - bool Contains([NotNull] object instance, [NotNull] object value); - - /// - /// 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. - /// - bool Remove([NotNull] object instance, [NotNull] object value); - - /// - /// 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. - /// - object Create(); - - /// - /// 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. - /// - object GetOrCreate([NotNull] object instance, bool forMaterialization); - - /// - /// 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. - /// - Type CollectionType { get; } - } -} diff --git a/src/EFCore/Metadata/Internal/IClrPropertyGetter.cs b/src/EFCore/Metadata/Internal/IClrPropertyGetter.cs deleted file mode 100644 index a278148acf3..00000000000 --- a/src/EFCore/Metadata/Internal/IClrPropertyGetter.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using JetBrains.Annotations; - -namespace Microsoft.EntityFrameworkCore.Metadata.Internal -{ - /// - /// 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. - /// - public interface IClrPropertyGetter - { - /// - /// 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. - /// - object GetClrValue([NotNull] object instance); - - /// - /// 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. - /// - bool HasDefaultValue([NotNull] object instance); - } -} diff --git a/src/EFCore/Metadata/Internal/IClrPropertySetter.cs b/src/EFCore/Metadata/Internal/IClrPropertySetter.cs deleted file mode 100644 index 027140f7cc8..00000000000 --- a/src/EFCore/Metadata/Internal/IClrPropertySetter.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using JetBrains.Annotations; - -namespace Microsoft.EntityFrameworkCore.Metadata.Internal -{ - /// - /// 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. - /// - public interface IClrPropertySetter - { - /// - /// 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. - /// - void SetClrValue([NotNull] object instance, [CanBeNull] object value); - } -} diff --git a/src/EFCore/Metadata/Internal/NavigationExtensions.cs b/src/EFCore/Metadata/Internal/NavigationExtensions.cs index f2e928ba6e8..0fc1f844ca6 100644 --- a/src/EFCore/Metadata/Internal/NavigationExtensions.cs +++ b/src/EFCore/Metadata/Internal/NavigationExtensions.cs @@ -17,15 +17,6 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Internal /// public static class NavigationExtensions { - /// - /// 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. - /// - public static IClrCollectionAccessor GetCollectionAccessor([NotNull] this INavigation navigation) - => navigation.AsNavigation().CollectionAccessor; - /// /// 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 diff --git a/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs b/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs index 0d66dcce95d..858d289d844 100644 --- a/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs +++ b/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs @@ -72,7 +72,7 @@ private static Func CreateCurrentValueGetter propertyBase.AsPropertyBase().Accessors; - /// - /// 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. - /// - public static IClrPropertyGetter GetGetter([NotNull] this IPropertyBase propertyBase) - => propertyBase.AsPropertyBase().Getter; - - /// - /// 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. - /// - public static IClrPropertySetter GetSetter([NotNull] this IPropertyBase propertyBase) - => propertyBase.AsPropertyBase().Setter; - - /// - /// 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. - /// - public static IClrPropertySetter GetMaterializationSetter([NotNull] this IPropertyBase propertyBase) - => propertyBase.AsPropertyBase().MaterializationSetter; - /// /// 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 @@ -121,25 +93,6 @@ public static MemberInfo GetIdentifyingMemberInfo( [NotNull] this IPropertyBase propertyBase) => propertyBase.PropertyInfo ?? (MemberInfo)propertyBase.FieldInfo; - /// - /// 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. - /// - public static MemberInfo GetMemberInfo( - [NotNull] this IPropertyBase propertyBase, - bool forConstruction, - bool forSet) - { - if (propertyBase.TryGetMemberInfo(forConstruction, forSet, out var memberInfo, out var errorMessage)) - { - return memberInfo; - } - - throw new InvalidOperationException(errorMessage); - } - /// /// 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 diff --git a/src/EFCore/Query/EntityMaterializerSource.cs b/src/EFCore/Query/EntityMaterializerSource.cs index 6adee58520d..76b5b77c263 100644 --- a/src/EFCore/Query/EntityMaterializerSource.cs +++ b/src/EFCore/Query/EntityMaterializerSource.cs @@ -11,7 +11,7 @@ using System.Threading; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Storage; @@ -122,7 +122,7 @@ var blockExpressions foreach (var property in properties) { - var memberInfo = property.GetMemberInfo(forConstruction: true, forSet: true); + var memberInfo = property.GetMemberInfo(forMaterialization: true, forSet: true); var readValueExpression = property is IServiceProperty serviceProperty diff --git a/test/EFCore.Tests/Metadata/Internal/ClrCollectionAccessorFactoryTest.cs b/test/EFCore.Tests/Metadata/Internal/ClrCollectionAccessorFactoryTest.cs index 35c558e662c..acd0b6f3306 100644 --- a/test/EFCore.Tests/Metadata/Internal/ClrCollectionAccessorFactoryTest.cs +++ b/test/EFCore.Tests/Metadata/Internal/ClrCollectionAccessorFactoryTest.cs @@ -49,11 +49,11 @@ private class FakeNavigation : INavigation, IClrCollectionAccessor public FieldInfo FieldInfo { get; } public IEntityType DeclaringEntityType { get; } public IForeignKey ForeignKey { get; } - public bool Add(object instance, object value, bool forMaterialization) => throw new NotImplementedException(); - public bool Contains(object instance, object value) => throw new NotImplementedException(); - public bool Remove(object instance, object value) => throw new NotImplementedException(); + public bool Add(object entity, object value, bool forMaterialization) => throw new NotImplementedException(); + public bool Contains(object entity, object value) => throw new NotImplementedException(); + public bool Remove(object entity, object value) => throw new NotImplementedException(); public object Create() => throw new NotImplementedException(); - public object GetOrCreate(object instance, bool forMaterialization) => throw new NotImplementedException(); + public object GetOrCreate(object entity, bool forMaterialization) => throw new NotImplementedException(); public Type CollectionType { get; } } diff --git a/test/EFCore.Tests/Metadata/Internal/ClrPropertyGetterFactoryTest.cs b/test/EFCore.Tests/Metadata/Internal/ClrPropertyGetterFactoryTest.cs index bcc4e0f575a..e3b732bd98b 100644 --- a/test/EFCore.Tests/Metadata/Internal/ClrPropertyGetterFactoryTest.cs +++ b/test/EFCore.Tests/Metadata/Internal/ClrPropertyGetterFactoryTest.cs @@ -23,8 +23,8 @@ public void Property_is_returned_if_it_implements_IClrPropertyGetter() private class FakeProperty : IProperty, IClrPropertyGetter { - public object GetClrValue(object instance) => throw new NotImplementedException(); - public bool HasDefaultValue(object instance) => throw new NotImplementedException(); + public object GetClrValue(object entity) => throw new NotImplementedException(); + public bool HasDefaultValue(object entity) => throw new NotImplementedException(); public object this[string name] => throw new NotImplementedException(); public IAnnotation FindAnnotation(string name) => throw new NotImplementedException(); public IEnumerable GetAnnotations() => throw new NotImplementedException(); diff --git a/test/EFCore.Tests/Metadata/Internal/PropertyBaseTest.cs b/test/EFCore.Tests/Metadata/Internal/PropertyBaseTest.cs index 24595e78dd6..bf4e077d8ae 100644 --- a/test/EFCore.Tests/Metadata/Internal/PropertyBaseTest.cs +++ b/test/EFCore.Tests/Metadata/Internal/PropertyBaseTest.cs @@ -687,7 +687,7 @@ private void MemberInfoTestCommon( string failMessage = null; try { - var memberInfo = propertyBase.GetMemberInfo(forConstruction: true, forSet: true); + var memberInfo = propertyBase.GetMemberInfo(forMaterialization: true, forSet: true); Assert.Equal(forConstruction, memberInfo?.Name); var propertyInfo = memberInfo as PropertyInfo; @@ -704,7 +704,7 @@ private void MemberInfoTestCommon( try { - var memberInfo = propertyBase.GetMemberInfo(forConstruction: false, forSet: true); + var memberInfo = propertyBase.GetMemberInfo(forMaterialization: false, forSet: true); Assert.Equal(forSet, memberInfo?.Name); var propertyInfo = memberInfo as PropertyInfo; @@ -721,7 +721,7 @@ private void MemberInfoTestCommon( try { - var memberInfo = propertyBase.GetMemberInfo(forConstruction: false, forSet: false); + var memberInfo = propertyBase.GetMemberInfo(forMaterialization: false, forSet: false); Assert.Equal(forGet, memberInfo?.Name); var propertyInfo = memberInfo as PropertyInfo;