diff --git a/src/EFCore.Abstractions/ChangeTracking/Internal/ObservableBackedBindingList.cs b/src/EFCore.Abstractions/ChangeTracking/Internal/ObservableBackedBindingList.cs index dac72129f99..917b6386374 100644 --- a/src/EFCore.Abstractions/ChangeTracking/Internal/ObservableBackedBindingList.cs +++ b/src/EFCore.Abstractions/ChangeTracking/Internal/ObservableBackedBindingList.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Specialized; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal; @@ -12,6 +13,8 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal; /// 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. /// +[RequiresUnreferencedCode( + "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] public class ObservableBackedBindingList : SortableBindingList { private bool _addingNewInstance; @@ -28,6 +31,8 @@ public class ObservableBackedBindingList : SortableBindingList /// 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. /// + [RequiresUnreferencedCode( + "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] public ObservableBackedBindingList(ICollection observableCollection) : base(observableCollection.ToList()) { diff --git a/src/EFCore.Abstractions/ChangeTracking/Internal/SortableBindingList.cs b/src/EFCore.Abstractions/ChangeTracking/Internal/SortableBindingList.cs index c532e52c6fc..d51d999793f 100644 --- a/src/EFCore.Abstractions/ChangeTracking/Internal/SortableBindingList.cs +++ b/src/EFCore.Abstractions/ChangeTracking/Internal/SortableBindingList.cs @@ -3,6 +3,7 @@ using System.Collections; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal; @@ -12,6 +13,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal; /// 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. /// +[RequiresUnreferencedCode("Raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] public class SortableBindingList : BindingList { private bool _isSorted; @@ -24,6 +26,7 @@ public class SortableBindingList : BindingList /// 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. /// + [RequiresUnreferencedCode("Raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] public SortableBindingList(List list) : base(list) { @@ -35,6 +38,13 @@ public SortableBindingList(List list) /// 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. /// + [RequiresUnreferencedCode("Requires accessing property 'Default' on the property descriptor's type")] + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2046", + Justification = + "This method is an override, and the base method isn't annotated with RequiresUnreferencedCode. " + + "The entire type is marked with RequiresUnreferencedCode.")] protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) { if (PropertyComparer.CanSort(prop.PropertyType)) @@ -101,6 +111,7 @@ private sealed class PropertyComparer : Comparer private readonly ListSortDirection _direction; private readonly PropertyDescriptor _prop; + [RequiresUnreferencedCode("Requires accessing property 'Default' on the property descriptor's type")] public PropertyComparer(PropertyDescriptor prop, ListSortDirection direction) { if (!prop.ComponentType.IsAssignableFrom(typeof(T))) diff --git a/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs b/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs index ed2825ce801..07458d41a35 100644 --- a/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs +++ b/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.ObjectModel; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.EntityFrameworkCore.ChangeTracking; @@ -25,6 +26,8 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking; /// /// /// The type of elements in the collection. +[RequiresUnreferencedCode( + "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] public class ObservableCollectionListSource : ObservableCollection, IListSource where T : class { @@ -71,6 +74,14 @@ bool IListSource.ContainsListCollection /// /// An in sync with the ObservableCollection. /// + [RequiresUnreferencedCode( + "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2046", + Justification = + "This method is an interface implementation, and the interface method isn't annotated with RequiresUnreferencedCode. " + + "The entire type is marked with RequiresUnreferencedCode.")] IList IListSource.GetList() => _bindingList ??= this.ToBindingList(); } diff --git a/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs b/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs index 74316edd97b..adbfbc7f0e3 100644 --- a/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs +++ b/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore; @@ -28,5 +29,6 @@ public EntityTypeConfigurationAttribute(Type entityConfigurationType) /// /// Type of the entity type configuration. /// + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.Interfaces)] public Type EntityTypeConfigurationType { get; } } diff --git a/src/EFCore.Abstractions/ObservableCollectionExtensions.cs b/src/EFCore.Abstractions/ObservableCollectionExtensions.cs index 7917c9c349d..92a4e4fe646 100644 --- a/src/EFCore.Abstractions/ObservableCollectionExtensions.cs +++ b/src/EFCore.Abstractions/ObservableCollectionExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.ObjectModel; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; namespace Microsoft.EntityFrameworkCore; @@ -23,6 +24,8 @@ public static class ObservableCollectionExtensions /// The element type. /// The collection that the binding list will stay in sync with. /// The binding list. + [RequiresUnreferencedCode( + "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] public static BindingList ToBindingList(this ObservableCollection source) where T : class => new ObservableBackedBindingList(source); diff --git a/src/EFCore.Relational/Migrations/IMigrator.cs b/src/EFCore.Relational/Migrations/IMigrator.cs index ba62e50338a..b05fa5a07f5 100644 --- a/src/EFCore.Relational/Migrations/IMigrator.cs +++ b/src/EFCore.Relational/Migrations/IMigrator.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Migrations; /// @@ -30,6 +32,7 @@ public interface IMigrator /// /// The target migration to migrate the database to, or to migrate to the latest. /// + [RequiresUnreferencedCode("Migration generation currently isn't compatible with trimming")] void Migrate(string? targetMigration = null); /// @@ -45,6 +48,7 @@ public interface IMigrator /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation /// If the is canceled. + [RequiresUnreferencedCode("Migration generation currently isn't compatible with trimming")] Task MigrateAsync( string? targetMigration = null, CancellationToken cancellationToken = default); @@ -66,6 +70,7 @@ Task MigrateAsync( /// The options to use when generating SQL for migrations. /// /// The generated script. + [RequiresUnreferencedCode("Migration generation currently isn't compatible with trimming")] string GenerateScript( string? fromMigration = null, string? toMigration = null, diff --git a/src/EFCore/ChangeTracking/GeometryValueComparer.cs b/src/EFCore/ChangeTracking/GeometryValueComparer.cs index 6fbdd895ac7..9271da7171a 100644 --- a/src/EFCore/ChangeTracking/GeometryValueComparer.cs +++ b/src/EFCore/ChangeTracking/GeometryValueComparer.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.ChangeTracking; /// @@ -9,7 +11,8 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking; /// /// See EF Core value comparers for more information and examples. /// -public class GeometryValueComparer : ValueComparer +public class GeometryValueComparer<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TGeometry> + : ValueComparer { /// /// Initializes a new instance of the class. diff --git a/src/EFCore/ChangeTracking/Internal/IdentityMapFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/IdentityMapFactoryFactory.cs index ab9e5768d5d..682d5d75b9d 100644 --- a/src/EFCore/ChangeTracking/Internal/IdentityMapFactoryFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/IdentityMapFactoryFactory.cs @@ -20,8 +20,8 @@ public class IdentityMapFactoryFactory /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Func Create(IKey key) - => (Func)typeof(IdentityMapFactoryFactory).GetTypeInfo() - .GetDeclaredMethod(nameof(CreateFactory))! + => (Func)typeof(IdentityMapFactoryFactory) + .GetMethod(nameof(CreateFactory), BindingFlags.NonPublic | BindingFlags.Static)! .MakeGenericMethod(key.GetKeyType()) .Invoke(null, new object[] { key })!; diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs index 666fce4cce8..7e235b36e0d 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs @@ -3,6 +3,7 @@ using System.Collections.Specialized; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Internal; @@ -829,8 +830,9 @@ private void MarkShadowPropertiesNotSet(IEntityType entityType) public void MarkUnknown(IProperty property) => _stateData.FlagProperty(property.GetIndex(), PropertyFlag.Unknown, true); - internal static readonly MethodInfo ReadShadowValueMethod - = typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadShadowValue))!; + internal static MethodInfo MakeReadShadowValueMethod(Type type) + => typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadShadowValue))! + .MakeGenericMethod(type); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -841,38 +843,63 @@ internal static readonly MethodInfo ReadShadowValueMethod private T ReadShadowValue(int shadowIndex) => _shadowValues.GetValue(shadowIndex); - internal static readonly MethodInfo ReadOriginalValueMethod + private static readonly MethodInfo ReadOriginalValueMethod = typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadOriginalValue))!; + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060", + Justification = "MakeGenericMethod wrapper, see https://github.com/dotnet/linker/issues/2482")] + internal static MethodInfo MakeReadOriginalValueMethod(Type type) + => ReadOriginalValueMethod.MakeGenericMethod(type); + [UsedImplicitly] private T ReadOriginalValue(IProperty property, int originalValueIndex) => _originalValues.GetValue(this, property, originalValueIndex); - internal static readonly MethodInfo ReadRelationshipSnapshotValueMethod + private static readonly MethodInfo ReadRelationshipSnapshotValueMethod = typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadRelationshipSnapshotValue))!; + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060", + Justification = "MakeGenericMethod wrapper, see https://github.com/dotnet/linker/issues/2482")] + internal static MethodInfo MakeReadRelationshipSnapshotValueMethod(Type type) + => ReadRelationshipSnapshotValueMethod.MakeGenericMethod(type); + [UsedImplicitly] private T ReadRelationshipSnapshotValue(IPropertyBase propertyBase, int relationshipSnapshotIndex) => _relationshipsSnapshot.GetValue(this, propertyBase, relationshipSnapshotIndex); - internal static readonly MethodInfo ReadStoreGeneratedValueMethod + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060", + Justification = "MakeGenericMethod wrapper, see https://github.com/dotnet/linker/issues/2482")] + internal static MethodInfo MakeReadStoreGeneratedValueMethod(Type type) + => ReadStoreGeneratedValueMethod.MakeGenericMethod(type); + + private static readonly MethodInfo ReadStoreGeneratedValueMethod = typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadStoreGeneratedValue))!; [UsedImplicitly] private T ReadStoreGeneratedValue(int storeGeneratedIndex) => _storeGeneratedValues.GetValue(storeGeneratedIndex); - internal static readonly MethodInfo ReadTemporaryValueMethod + private static readonly MethodInfo ReadTemporaryValueMethod = typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadTemporaryValue))!; + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060", + Justification = "MakeGenericMethod wrapper, see https://github.com/dotnet/linker/issues/2482")] + internal static MethodInfo MakeReadTemporaryValueMethod(Type type) + => ReadTemporaryValueMethod.MakeGenericMethod(type); + [UsedImplicitly] private T ReadTemporaryValue(int storeGeneratedIndex) => _temporaryValues.GetValue(storeGeneratedIndex); - internal static readonly MethodInfo GetCurrentValueMethod + private static readonly MethodInfo GetCurrentValueMethod = typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethods(nameof(GetCurrentValue)).Single( m => m.IsGenericMethod); + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060", + Justification = "MakeGenericMethod wrapper, see https://github.com/dotnet/linker/issues/2482")] + internal static MethodInfo MakeGetCurrentValueMethod(Type type) + => GetCurrentValueMethod.MakeGenericMethod(type); + /// /// 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/ChangeTracking/Internal/Snapshot.cs b/src/EFCore/ChangeTracking/Internal/Snapshot.cs index 96912cb0263..1c447b29add 100644 --- a/src/EFCore/ChangeTracking/Internal/Snapshot.cs +++ b/src/EFCore/ChangeTracking/Internal/Snapshot.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal; /// @@ -82,6 +84,7 @@ public static Delegate[] CreateReaders() /// 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. /// + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] public static Type CreateSnapshotType(Type[] types) => types.Length switch { diff --git a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs index f93cc8a1e3c..112729c8681 100644 --- a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs @@ -219,7 +219,7 @@ protected virtual Expression CreateReadShadowValueExpression( IPropertyBase property) => Expression.Call( parameter, - InternalEntityEntry.ReadShadowValueMethod.MakeGenericMethod((property as IProperty)?.ClrType ?? typeof(object)), + InternalEntityEntry.MakeReadShadowValueMethod((property as IProperty)?.ClrType ?? typeof(object)), Expression.Constant(property.GetShadowIndex())); /// @@ -233,7 +233,7 @@ protected virtual Expression CreateReadValueExpression( IPropertyBase property) => Expression.Call( parameter, - InternalEntityEntry.GetCurrentValueMethod.MakeGenericMethod(property.ClrType), + InternalEntityEntry.MakeGetCurrentValueMethod(property.ClrType), Expression.Constant(property, typeof(IProperty))); /// diff --git a/src/EFCore/ChangeTracking/Internal/TemporaryValuesFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/TemporaryValuesFactoryFactory.cs index b36c1884d00..cc9e963e82f 100644 --- a/src/EFCore/ChangeTracking/Internal/TemporaryValuesFactoryFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/TemporaryValuesFactoryFactory.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal; /// @@ -18,7 +20,7 @@ public class TemporaryValuesFactoryFactory : SidecarValuesFactoryFactory /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override Expression CreateSnapshotExpression( - Type? entityType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type? entityType, ParameterExpression parameter, Type[] types, IList propertyBases) diff --git a/src/EFCore/ChangeTracking/LocalView.cs b/src/EFCore/ChangeTracking/LocalView.cs index 2c05bc90f13..ffaa0bb46ae 100644 --- a/src/EFCore/ChangeTracking/LocalView.cs +++ b/src/EFCore/ChangeTracking/LocalView.cs @@ -5,6 +5,7 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Internal; @@ -45,7 +46,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking; /// /// /// The type of the entity in the local view. -public class LocalView : +public class LocalView<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity> : ICollection, INotifyCollectionChanged, INotifyPropertyChanged, @@ -473,6 +474,8 @@ private void OnCollectionChanged(NotifyCollectionChangedAction action, object it /// examples. /// /// The binding list. + [RequiresUnreferencedCode( + "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] public virtual BindingList ToBindingList() => _bindingList ??= new ObservableBackedBindingList(ToObservableCollection()); diff --git a/src/EFCore/ChangeTracking/ValueComparer.cs b/src/EFCore/ChangeTracking/ValueComparer.cs index 8feeed224e0..882742fa0e5 100644 --- a/src/EFCore/ChangeTracking/ValueComparer.cs +++ b/src/EFCore/ChangeTracking/ValueComparer.cs @@ -182,7 +182,12 @@ public virtual Expression ExtractSnapshotBody(Expression expression) /// implements it. This is usually used when byte arrays act as keys. /// /// The . - public static ValueComparer CreateDefault(Type type, bool favorStructuralComparisons) + public static ValueComparer CreateDefault( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods + | DynamicallyAccessedMemberTypes.NonPublicMethods + | DynamicallyAccessedMemberTypes.PublicProperties)] + Type type, + bool favorStructuralComparisons) { var nonNullableType = type.UnwrapNullableType(); @@ -212,12 +217,20 @@ public static ValueComparer CreateDefault(Type type, bool favorStructuralCompari ? typeof(DefaultValueComparer<>) : typeof(ValueComparer<>); - return (ValueComparer)Activator.CreateInstance( - comparerType.MakeGenericType(type), - new object[] { favorStructuralComparisons })!; + return CreateInstance(); + + [UnconditionalSuppressMessage( + "ReflectionAnalysis", "IL2055", Justification = + "We only create ValueComparer or DefaultValueComparer whose generic type parameter requires Methods/Properties, " + + "and our type argument is properly annotated for those.")] + ValueComparer CreateInstance() + => (ValueComparer)Activator.CreateInstance( + comparerType.MakeGenericType(type), + new object[] { favorStructuralComparisons })!; } - internal class DefaultValueComparer : ValueComparer + // PublicMethods is required to preserve e.g. GetHashCode + internal class DefaultValueComparer<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> : ValueComparer { public DefaultValueComparer(bool favorStructuralComparisons) : base(favorStructuralComparisons) diff --git a/src/EFCore/ChangeTracking/ValueComparer`.cs b/src/EFCore/ChangeTracking/ValueComparer`.cs index 794f987700e..4712356813b 100644 --- a/src/EFCore/ChangeTracking/ValueComparer`.cs +++ b/src/EFCore/ChangeTracking/ValueComparer`.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; using ExpressionExtensions = Microsoft.EntityFrameworkCore.Infrastructure.ExpressionExtensions; @@ -25,7 +26,12 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking; /// /// /// The type. -public class ValueComparer : ValueComparer, IEqualityComparer +// PublicMethods is required to preserve e.g. GetHashCode +public class ValueComparer + <[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods + | DynamicallyAccessedMemberTypes.NonPublicMethods + | DynamicallyAccessedMemberTypes.PublicProperties)] T> + : ValueComparer, IEqualityComparer { private Func? _equals; private Func? _hashCode; @@ -178,6 +184,7 @@ protected static Expression> CreateDefaultSnapshotExpression(bool fav return v => v; } + // Comparer implementation for arrays var sourceParameter = Expression.Parameter(typeof(T), "source"); var lengthVariable = Expression.Variable(typeof(int), "length"); var destinationVariable = Expression.Variable(typeof(T), "destination"); @@ -195,7 +202,7 @@ protected static Expression> CreateDefaultSnapshotExpression(bool fav Expression.Property(sourceParameter, typeof(T).GetTypeInfo().GetProperty(nameof(Array.Length))!)), Expression.Assign( destinationVariable, - Expression.NewArrayBounds(typeof(T).GetSequenceType(), lengthVariable)), + Expression.NewArrayBounds(typeof(T).GetElementType()!, lengthVariable)), Expression.Call( ArrayCopyMethod, sourceParameter, diff --git a/src/EFCore/DbContext.cs b/src/EFCore/DbContext.cs index 69ab260688e..a29e165496c 100644 --- a/src/EFCore/DbContext.cs +++ b/src/EFCore/DbContext.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Internal; @@ -78,6 +79,10 @@ public class DbContext : /// See DbContext lifetime, configuration, and initialization /// for more information and examples. /// + [RequiresUnreferencedCode( + "EF Core isn't fully compatible with trimming, and running the application may generate unexpected runtime failures. " + + "Some specific coding pattern are usually required to make trimming work properly, see https://aka.ms/efcore-docs-trimming for " + + "more details.")] protected DbContext() : this(new DbContextOptions()) { @@ -93,6 +98,10 @@ protected DbContext() /// Using DbContextOptions for more information and examples. /// /// The options for this context. + [RequiresUnreferencedCode( + "EF Core isn't fully compatible with trimming, and running the application may generate unexpected runtime failures. " + + "Some specific coding pattern are usually required to make trimming work properly, see https://aka.ms/efcore-docs-trimming for " + + "more details.")] public DbContext(DbContextOptions options) { Check.NotNull(options, nameof(options)); @@ -261,7 +270,9 @@ IExceptionDetector IDbContextDependencies.ExceptionDetector /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [EntityFrameworkInternal] - object IDbSetCache.GetOrAddSet(IDbSetSource source, Type type) + object IDbSetCache.GetOrAddSet( + IDbSetSource source, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) { CheckDisposed(); @@ -284,7 +295,10 @@ object IDbSetCache.GetOrAddSet(IDbSetSource source, Type type) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [EntityFrameworkInternal] - object IDbSetCache.GetOrAddSet(IDbSetSource source, string entityTypeName, Type type) + object IDbSetCache.GetOrAddSet( + IDbSetSource source, + string entityTypeName, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) { CheckDisposed(); @@ -328,7 +342,7 @@ IEnumerable IDbSetCache.GetSets() /// /// The type of entity for which a set should be returned. /// A set for the given entity type. - public virtual DbSet Set() + public virtual DbSet Set<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>() where TEntity : class => (DbSet)((IDbSetCache)this).GetOrAddSet(DbContextDependencies.SetSource, typeof(TEntity)); @@ -349,11 +363,11 @@ public virtual DbSet Set() /// The name for the shared-type entity type to use. /// The type of entity for which a set should be returned. /// A set for the given entity type. - public virtual DbSet Set(string name) + public virtual DbSet Set<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>(string name) where TEntity : class => (DbSet)((IDbSetCache)this).GetOrAddSet(DbContextDependencies.SetSource, name, typeof(TEntity)); - private IEntityFinder Finder(Type type) + private IEntityFinder Finder([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) { var entityType = Model.FindEntityType(type); if (entityType == null) @@ -2020,7 +2034,9 @@ public virtual void RemoveRange(IEnumerable entities) /// The type of entity to find. /// The values of the primary key for the entity to be found. /// The entity found, or . - public virtual object? Find(Type entityType, params object?[]? keyValues) + public virtual object? Find( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type entityType, + params object?[]? keyValues) { CheckDisposed(); @@ -2049,7 +2065,9 @@ public virtual void RemoveRange(IEnumerable entities) /// The type of entity to find. /// The values of the primary key for the entity to be found. /// The entity found, or . - public virtual ValueTask FindAsync(Type entityType, params object?[]? keyValues) + public virtual ValueTask FindAsync( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type entityType, + params object?[]? keyValues) { CheckDisposed(); @@ -2081,7 +2099,7 @@ public virtual void RemoveRange(IEnumerable entities) /// The entity found, or . /// If the is canceled. public virtual ValueTask FindAsync( - Type entityType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type entityType, object?[]? keyValues, CancellationToken cancellationToken) { @@ -2103,7 +2121,8 @@ public virtual void RemoveRange(IEnumerable entities) /// The type of entity to find. /// The values of the primary key for the entity to be found. /// The entity found, or . - public virtual TEntity? Find(params object?[]? keyValues) + public virtual TEntity? Find<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>( + params object?[]? keyValues) where TEntity : class { CheckDisposed(); @@ -2133,7 +2152,8 @@ public virtual void RemoveRange(IEnumerable entities) /// The type of entity to find. /// The values of the primary key for the entity to be found. /// The entity found, or . - public virtual ValueTask FindAsync(params object?[]? keyValues) + public virtual ValueTask FindAsync< + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>(params object?[]? keyValues) where TEntity : class { CheckDisposed(); @@ -2165,7 +2185,8 @@ public virtual void RemoveRange(IEnumerable entities) /// A to observe while waiting for the task to complete. /// The entity found, or . /// If the is canceled. - public virtual ValueTask FindAsync(object?[]? keyValues, CancellationToken cancellationToken) + public virtual ValueTask FindAsync<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>( + object?[]? keyValues, CancellationToken cancellationToken) where TEntity : class { CheckDisposed(); @@ -2232,4 +2253,14 @@ public override int GetHashCode() => base.GetHashCode(); #endregion + + internal const DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes = + System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors + // We preserve public properties on contexts to make sure DbSet properties - and in particular their setters - aren't trimmed. + // Since EF implicitly injects DbSet properties via reflection and the user doesn't contain any explicit use, setters get trimmed + // and our injection logic no longer recognizes them for injection. + // Note that this works only using the DI APIs (e.g. AddDbContext) or DbContextFactory, but not when the context is instantiated + // directly (there's no API accepting Type where we'd put [DynamicallyAccessedMemberTypes]). + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties; } diff --git a/src/EFCore/DbSet.cs b/src/EFCore/DbSet.cs index 09baeb9bc41..63e084ea9b8 100644 --- a/src/EFCore/DbSet.cs +++ b/src/EFCore/DbSet.cs @@ -3,6 +3,8 @@ using System.Collections; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore; @@ -40,7 +42,8 @@ namespace Microsoft.EntityFrameworkCore; /// /// /// The type of entity being operated on by this set. -public abstract class DbSet : IQueryable, IInfrastructure, IListSource +public abstract class DbSet<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity> + : IQueryable, IInfrastructure, IListSource where TEntity : class { /// diff --git a/src/EFCore/EF.CompileAsyncQuery.cs b/src/EFCore/EF.CompileAsyncQuery.cs index 77030f1b617..290b8eb8af7 100644 --- a/src/EFCore/EF.CompileAsyncQuery.cs +++ b/src/EFCore/EF.CompileAsyncQuery.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Threading; @@ -22,7 +23,9 @@ public static partial class EF /// The query result type. /// The LINQ query expression. /// A delegate that can be invoked to execute the compiled query. - public static Func> CompileAsyncQuery( + public static Func> CompileAsyncQuery< + TContext, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TResult>( Expression>> queryExpression) where TContext : DbContext where TResult : class diff --git a/src/EFCore/EF.cs b/src/EFCore/EF.cs index 57b650f9251..60f05cddaca 100644 --- a/src/EFCore/EF.cs +++ b/src/EFCore/EF.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore; /// @@ -17,6 +19,11 @@ public static partial class EF internal static readonly MethodInfo PropertyMethod = typeof(EF).GetTypeInfo().GetDeclaredMethod(nameof(Property))!; + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060", + Justification = "EF.Property has no DynamicallyAccessedMembers annotations and is safe to construct.")] + internal static MethodInfo MakePropertyMethod(Type type) + => PropertyMethod.MakeGenericMethod(type); + /// /// This flag is set to when code is being run from a design-time tool, such /// as "dotnet ef" or one of the Package Manager Console PowerShell commands "Add-Migration", "Update-Database", etc. diff --git a/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs b/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs index 53050b01f3e..0eb2ef4abd7 100644 --- a/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs +++ b/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Microsoft.EntityFrameworkCore.Query.Internal; @@ -11,6 +12,13 @@ namespace Microsoft.EntityFrameworkCore; /// /// Entity Framework LINQ related extension methods. /// +[UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2060", + Justification = + "MakeGenericMethod is used in this class to create MethodCallExpression nodes, but only if the method in question is called " + + "from user code - so it's never trimmed. After https://github.com/dotnet/linker/issues/2482 is fixed, the suppression will no " + + "longer be necessary.")] public static class EntityFrameworkQueryableExtensions { /// diff --git a/src/EFCore/Extensions/EntityFrameworkServiceCollectionExtensions.cs b/src/EFCore/Extensions/EntityFrameworkServiceCollectionExtensions.cs index 6a21dca25f1..3ed8d2a0feb 100644 --- a/src/EFCore/Extensions/EntityFrameworkServiceCollectionExtensions.cs +++ b/src/EFCore/Extensions/EntityFrameworkServiceCollectionExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -54,11 +55,12 @@ public static class EntityFrameworkServiceCollectionExtensions /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContext( - this IServiceCollection serviceCollection, - Action? optionsAction = null, - ServiceLifetime contextLifetime = ServiceLifetime.Scoped, - ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) + public static IServiceCollection AddDbContext + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext>( + this IServiceCollection serviceCollection, + Action? optionsAction = null, + ServiceLifetime contextLifetime = ServiceLifetime.Scoped, + ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContext : DbContext => AddDbContext(serviceCollection, optionsAction, contextLifetime, optionsLifetime); @@ -105,11 +107,12 @@ public static IServiceCollection AddDbContext( /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContext( - this IServiceCollection serviceCollection, - Action? optionsAction = null, - ServiceLifetime contextLifetime = ServiceLifetime.Scoped, - ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) + public static IServiceCollection AddDbContext + ( + this IServiceCollection serviceCollection, + Action? optionsAction = null, + ServiceLifetime contextLifetime = ServiceLifetime.Scoped, + ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContextImplementation : DbContext, TContextService => AddDbContext( serviceCollection, @@ -156,10 +159,11 @@ public static IServiceCollection AddDbContext /// Sets the maximum number of instances retained by the pool. Defaults to 1024. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContextPool( - this IServiceCollection serviceCollection, - Action optionsAction, - int poolSize = DbContextPool.DefaultPoolSize) + public static IServiceCollection AddDbContextPool + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext>( + this IServiceCollection serviceCollection, + Action optionsAction, + int poolSize = DbContextPool.DefaultPoolSize) where TContext : DbContext => AddDbContextPool(serviceCollection, optionsAction, poolSize); @@ -203,10 +207,11 @@ public static IServiceCollection AddDbContextPool( /// /// Sets the maximum number of instances retained by the pool. Defaults to 1024. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContextPool( - this IServiceCollection serviceCollection, - Action optionsAction, - int poolSize = DbContextPool.DefaultPoolSize) + public static IServiceCollection AddDbContextPool + ( + this IServiceCollection serviceCollection, + Action optionsAction, + int poolSize = DbContextPool.DefaultPoolSize) where TContextImplementation : DbContext, TContextService where TContextService : class { @@ -262,10 +267,11 @@ public static IServiceCollection AddDbContextPool /// Sets the maximum number of instances retained by the pool. Defaults to 1024. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContextPool( - this IServiceCollection serviceCollection, - Action optionsAction, - int poolSize = DbContextPool.DefaultPoolSize) + public static IServiceCollection AddDbContextPool + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext>( + this IServiceCollection serviceCollection, + Action optionsAction, + int poolSize = DbContextPool.DefaultPoolSize) where TContext : DbContext => AddDbContextPool(serviceCollection, optionsAction, poolSize); @@ -318,10 +324,11 @@ public static IServiceCollection AddDbContextPool( /// /// Sets the maximum number of instances retained by the pool. Defaults to 1024. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContextPool( - this IServiceCollection serviceCollection, - Action optionsAction, - int poolSize = DbContextPool.DefaultPoolSize) + public static IServiceCollection AddDbContextPool + ( + this IServiceCollection serviceCollection, + Action optionsAction, + int poolSize = DbContextPool.DefaultPoolSize) where TContextImplementation : DbContext, TContextService where TContextService : class { @@ -343,7 +350,7 @@ public static IServiceCollection AddDbContextPool( + private static void AddPoolingOptions<[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext>( IServiceCollection serviceCollection, Action optionsAction, int poolSize) @@ -396,10 +403,11 @@ private static void AddPoolingOptions( /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContext( - this IServiceCollection serviceCollection, - ServiceLifetime contextLifetime, - ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) + public static IServiceCollection AddDbContext + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext>( + this IServiceCollection serviceCollection, + ServiceLifetime contextLifetime, + ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContext : DbContext => AddDbContext(serviceCollection, contextLifetime, optionsLifetime); @@ -430,10 +438,11 @@ public static IServiceCollection AddDbContext( /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContext( - this IServiceCollection serviceCollection, - ServiceLifetime contextLifetime, - ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) + public static IServiceCollection AddDbContext + ( + this IServiceCollection serviceCollection, + ServiceLifetime contextLifetime, + ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContextImplementation : DbContext, TContextService where TContextService : class => AddDbContext( @@ -500,11 +509,12 @@ public static IServiceCollection AddDbContextThe lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContext( - this IServiceCollection serviceCollection, - Action? optionsAction, - ServiceLifetime contextLifetime = ServiceLifetime.Scoped, - ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) + public static IServiceCollection AddDbContext + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext>( + this IServiceCollection serviceCollection, + Action? optionsAction, + ServiceLifetime contextLifetime = ServiceLifetime.Scoped, + ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContext : DbContext => AddDbContext(serviceCollection, optionsAction, contextLifetime, optionsLifetime); @@ -561,11 +571,12 @@ public static IServiceCollection AddDbContext( /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContext( - this IServiceCollection serviceCollection, - Action? optionsAction, - ServiceLifetime contextLifetime = ServiceLifetime.Scoped, - ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) + public static IServiceCollection AddDbContext + ( + this IServiceCollection serviceCollection, + Action? optionsAction, + ServiceLifetime contextLifetime = ServiceLifetime.Scoped, + ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContextImplementation : DbContext, TContextService { if (contextLifetime == ServiceLifetime.Singleton) @@ -660,10 +671,11 @@ public static IServiceCollection AddDbContext /// /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContextFactory( - this IServiceCollection serviceCollection, - Action? optionsAction = null, - ServiceLifetime lifetime = ServiceLifetime.Singleton) + public static IServiceCollection AddDbContextFactory + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext>( + this IServiceCollection serviceCollection, + Action? optionsAction = null, + ServiceLifetime lifetime = ServiceLifetime.Singleton) where TContext : DbContext => AddDbContextFactory>(serviceCollection, optionsAction, lifetime); @@ -728,7 +740,9 @@ public static IServiceCollection AddDbContextFactory( /// The default is /// /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContextFactory( + public static IServiceCollection AddDbContextFactory + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TFactory>( this IServiceCollection serviceCollection, Action? optionsAction = null, ServiceLifetime lifetime = ServiceLifetime.Singleton) @@ -805,10 +819,11 @@ public static IServiceCollection AddDbContextFactory( /// The default is /// /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContextFactory( - this IServiceCollection serviceCollection, - Action optionsAction, - ServiceLifetime lifetime = ServiceLifetime.Singleton) + public static IServiceCollection AddDbContextFactory + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext>( + this IServiceCollection serviceCollection, + Action optionsAction, + ServiceLifetime lifetime = ServiceLifetime.Singleton) where TContext : DbContext => AddDbContextFactory>(serviceCollection, optionsAction, lifetime); @@ -881,7 +896,9 @@ public static IServiceCollection AddDbContextFactory( /// The default is /// /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddDbContextFactory( + public static IServiceCollection AddDbContextFactory + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TFactory>( this IServiceCollection serviceCollection, Action? optionsAction, ServiceLifetime lifetime = ServiceLifetime.Singleton) @@ -948,10 +965,11 @@ public static IServiceCollection AddDbContextFactory( /// /// Sets the maximum number of instances retained by the pool. Defaults to 1024. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddPooledDbContextFactory( - this IServiceCollection serviceCollection, - Action optionsAction, - int poolSize = DbContextPool.DefaultPoolSize) + public static IServiceCollection AddPooledDbContextFactory + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext>( + this IServiceCollection serviceCollection, + Action optionsAction, + int poolSize = DbContextPool.DefaultPoolSize) where TContext : DbContext { Check.NotNull(optionsAction, nameof(optionsAction)); @@ -998,10 +1016,11 @@ public static IServiceCollection AddPooledDbContextFactory( /// /// Sets the maximum number of instances retained by the pool. Defaults to 1024. /// The same service collection so that multiple calls can be chained. - public static IServiceCollection AddPooledDbContextFactory( - this IServiceCollection serviceCollection, - Action optionsAction, - int poolSize = DbContextPool.DefaultPoolSize) + public static IServiceCollection AddPooledDbContextFactory + <[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext>( + this IServiceCollection serviceCollection, + Action optionsAction, + int poolSize = DbContextPool.DefaultPoolSize) where TContext : DbContext { Check.NotNull(optionsAction, nameof(optionsAction)); diff --git a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs index 313d5192590..c986f25059d 100644 --- a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs +++ b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs @@ -225,7 +225,7 @@ static Expression GenerateEqualExpression( && !(nonNullableType == typeof(bool) || nonNullableType.IsNumeric() || nonNullableType.IsEnum) ? Infrastructure.ExpressionExtensions.CreateEqualsExpression( Expression.Call( - EF.PropertyMethod.MakeGenericMethod(typeof(object)), + EF.MakePropertyMethod(typeof(object)), entityParameterExpression, Expression.Constant(property.Name, typeof(string))), Expression.Call( @@ -234,7 +234,7 @@ static Expression GenerateEqualExpression( Expression.Constant(i))) : Expression.Equal( Expression.Call( - EF.PropertyMethod.MakeGenericMethod(property.ClrType), + EF.MakePropertyMethod(property.ClrType), entityParameterExpression, Expression.Constant(property.Name, typeof(string))), Expression.Convert( diff --git a/src/EFCore/Extensions/Internal/TypeExtensions.cs b/src/EFCore/Extensions/Internal/TypeExtensions.cs index 4ea23b8fd63..3327bf60bc6 100644 --- a/src/EFCore/Extensions/Internal/TypeExtensions.cs +++ b/src/EFCore/Extensions/Internal/TypeExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Text; // ReSharper disable once CheckNamespace @@ -20,7 +21,9 @@ public static class TypeExtensions /// 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 bool IsDefaultValue(this Type type, object? value) + public static bool IsDefaultValue( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] this Type type, + object? value) => (value?.Equals(type.GetDefaultValue()) != false); /// @@ -52,7 +55,9 @@ public static string GenerateParameterName(this Type type) /// 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 PropertyInfo? FindIndexerProperty(this Type type) + public static PropertyInfo? FindIndexerProperty( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] + this Type type) { var defaultPropertyAttribute = type.GetCustomAttributes().FirstOrDefault(); diff --git a/src/EFCore/IDbContextFactory.cs b/src/EFCore/IDbContextFactory.cs index 283affc28c0..180d1deb2e7 100644 --- a/src/EFCore/IDbContextFactory.cs +++ b/src/EFCore/IDbContextFactory.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore; /// @@ -10,7 +12,7 @@ namespace Microsoft.EntityFrameworkCore; /// See Using DbContextFactory for more information and examples. /// /// The type to create. -public interface IDbContextFactory +public interface IDbContextFactory<[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext> where TContext : DbContext { /// diff --git a/src/EFCore/IEntityTypeConfiguration.cs b/src/EFCore/IEntityTypeConfiguration.cs index 1282442fa6b..a2368584522 100644 --- a/src/EFCore/IEntityTypeConfiguration.cs +++ b/src/EFCore/IEntityTypeConfiguration.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore; /// @@ -17,7 +19,7 @@ namespace Microsoft.EntityFrameworkCore; /// examples. /// /// The entity type to be configured. -public interface IEntityTypeConfiguration +public interface IEntityTypeConfiguration<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity> where TEntity : class { /// diff --git a/src/EFCore/Infrastructure/DbSetProperty.cs b/src/EFCore/Infrastructure/DbSetProperty.cs index 673ebaba2f6..ddbe4c2664e 100644 --- a/src/EFCore/Infrastructure/DbSetProperty.cs +++ b/src/EFCore/Infrastructure/DbSetProperty.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; +using Microsoft.EntityFrameworkCore.Metadata.Internal; + namespace Microsoft.EntityFrameworkCore.Infrastructure; /// @@ -16,7 +19,7 @@ public readonly struct DbSetProperty /// The setter for DbSet property. public DbSetProperty( string name, - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, IClrPropertySetter? setter) { Name = name; @@ -32,6 +35,7 @@ public DbSetProperty( /// /// Gets the clr type of entity type this DbSet property represent. /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] public Type Type { get; } /// diff --git a/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs b/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs index 370cfc588a7..daaf29a6c2a 100644 --- a/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs +++ b/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.Infrastructure.Internal; @@ -359,7 +360,9 @@ private static IDbContextServices GetContextServices(IServiceProvider servicePro /// The contract for the service. /// The concrete type that implements the service. /// This builder, such that further calls can be chained. - public virtual EntityFrameworkServicesBuilder TryAdd() + public virtual EntityFrameworkServicesBuilder TryAdd< + TService, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>() where TService : class where TImplementation : class, TService => TryAdd(typeof(TService), typeof(TImplementation)); @@ -375,7 +378,9 @@ public virtual EntityFrameworkServicesBuilder TryAdd( /// The contract for the service. /// The concrete type that implements the service. /// This builder, such that further calls can be chained. - public virtual EntityFrameworkServicesBuilder TryAdd(Type serviceType, Type implementationType) + public virtual EntityFrameworkServicesBuilder TryAdd( + Type serviceType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { var characteristics = GetServiceCharacteristics(serviceType); @@ -402,7 +407,8 @@ public virtual EntityFrameworkServicesBuilder TryAdd(Type serviceType, Type impl /// The contract for the service. /// The factory that will create the service instance. /// This builder, such that further calls can be chained. - public virtual EntityFrameworkServicesBuilder TryAdd(Func factory) + public virtual EntityFrameworkServicesBuilder TryAdd + <[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(Func factory) where TService : class => TryAdd(typeof(TService), typeof(TService), factory); @@ -418,7 +424,8 @@ public virtual EntityFrameworkServicesBuilder TryAdd(FuncThe concrete type that implements the service. /// The factory that will create the service instance. /// This builder, such that further calls can be chained. - public virtual EntityFrameworkServicesBuilder TryAdd( + public virtual EntityFrameworkServicesBuilder TryAdd + ( Func factory) where TService : class where TImplementation : class, TService @@ -438,7 +445,7 @@ public virtual EntityFrameworkServicesBuilder TryAdd( /// This builder, such that further calls can be chained. public virtual EntityFrameworkServicesBuilder TryAdd( Type serviceType, - Type implementationType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, Func factory) { var characteristics = GetServiceCharacteristics(serviceType); diff --git a/src/EFCore/Infrastructure/ExpressionExtensions.cs b/src/EFCore/Infrastructure/ExpressionExtensions.cs index d8b432c47f0..5b7cf16c4c5 100644 --- a/src/EFCore/Infrastructure/ExpressionExtensions.cs +++ b/src/EFCore/Infrastructure/ExpressionExtensions.cs @@ -58,15 +58,18 @@ public static MemberExpression MakeMemberAccess( /// The member to which assignment will be made. /// The value that will be assigned. /// The representing the assignment binding. + [UnconditionalSuppressMessage( + "ReflectionAnalysis", "IL2077", + Justification = "AssignBinaryExpression is preserved via DynamicDependency below")] + [DynamicDependency(DynamicallyAccessedMemberTypes.All, "System.Linq.Expressions.AssignBinaryExpression", "System.Linq.Expressions")] public static Expression Assign( this MemberExpression memberExpression, Expression valueExpression) { - if (memberExpression.Member is FieldInfo fieldInfo - && fieldInfo.IsInitOnly) + if (memberExpression.Member is FieldInfo { IsInitOnly: true }) { return (BinaryExpression)Activator.CreateInstance( - AssignBinaryExpressionType, + GetAssignBinaryExpressionType(), BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { memberExpression, valueExpression }, @@ -74,10 +77,13 @@ public static Expression Assign( } return Expression.Assign(memberExpression, valueExpression); - } - private static readonly Type AssignBinaryExpressionType - = typeof(Expression).Assembly.GetType("System.Linq.Expressions.AssignBinaryExpression", throwOnError: true)!; + [UnconditionalSuppressMessage( + "ReflectionAnalysis", "IL2026", + Justification = "DynamicDependency ensures AssignBinaryExpression isn't trimmed")] + static Type GetAssignBinaryExpressionType() + => typeof(Expression).Assembly.GetType("System.Linq.Expressions.AssignBinaryExpression", throwOnError: true)!; + } /// /// If the given a method-call expression represents a call to , then this @@ -283,7 +289,7 @@ public static Expression CreateValueBufferReadValueExpression( int index, IPropertyBase? property) => Expression.Call( - ValueBufferTryReadValueMethod.MakeGenericMethod(type), + MakeValueBufferTryReadValueMethod(type), valueBuffer, Expression.Constant(index), Expression.Constant(property, typeof(IPropertyBase))); @@ -301,6 +307,11 @@ public static Expression CreateValueBufferReadValueExpression( public static readonly MethodInfo ValueBufferTryReadValueMethod = typeof(ExpressionExtensions).GetTypeInfo().GetDeclaredMethod(nameof(ValueBufferTryReadValue))!; + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060", + Justification = "ValueBufferTryReadValueMethod has no DynamicallyAccessedMembers annotations and is safe to construct.")] + private static MethodInfo MakeValueBufferTryReadValueMethod(Type type) + => ValueBufferTryReadValueMethod.MakeGenericMethod(type); + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static TValue ValueBufferTryReadValue( #pragma warning disable IDE0060 // Remove unused parameter @@ -372,7 +383,7 @@ private static Expression CreateEFPropertyExpression( } return Expression.Call( - EF.PropertyMethod.MakeGenericMethod(propertyType), + EF.MakePropertyMethod(propertyType), target, Expression.Constant(propertyName)); } diff --git a/src/EFCore/Infrastructure/IInternalServiceCollectionMap.cs b/src/EFCore/Infrastructure/IInternalServiceCollectionMap.cs index bdd9f206a21..de142e5be29 100644 --- a/src/EFCore/Infrastructure/IInternalServiceCollectionMap.cs +++ b/src/EFCore/Infrastructure/IInternalServiceCollectionMap.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Infrastructure; /// @@ -23,12 +25,14 @@ public interface IInternalServiceCollectionMap /// /// The dependency type. /// The same collection map so that further methods can be chained. - IInternalServiceCollectionMap AddDependencySingleton(); + IInternalServiceCollectionMap AddDependencySingleton< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TDependencies>(); /// /// Adds a dependency object. /// /// The dependency type. /// The same collection map so that further methods can be chained. - IInternalServiceCollectionMap AddDependencyScoped(); + IInternalServiceCollectionMap + AddDependencyScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TDependencies>(); } diff --git a/src/EFCore/Infrastructure/Internal/InternalServiceCollectionMap.cs b/src/EFCore/Infrastructure/Internal/InternalServiceCollectionMap.cs index 3bad83980d4..84d1ed9108c 100644 --- a/src/EFCore/Infrastructure/Internal/InternalServiceCollectionMap.cs +++ b/src/EFCore/Infrastructure/Internal/InternalServiceCollectionMap.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; namespace Microsoft.EntityFrameworkCore.Infrastructure.Internal; @@ -76,7 +77,8 @@ public virtual void AddNewDescriptor(IList indexes, ServiceDescriptor newDe /// 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 IInternalServiceCollectionMap AddDependencySingleton() + public virtual IInternalServiceCollectionMap AddDependencySingleton< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TDependencies>() => AddDependency(typeof(TDependencies), ServiceLifetime.Singleton); /// @@ -85,7 +87,8 @@ public virtual IInternalServiceCollectionMap AddDependencySingleton - public virtual IInternalServiceCollectionMap AddDependencyScoped() + public virtual IInternalServiceCollectionMap + AddDependencyScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TDependencies>() => AddDependency(typeof(TDependencies), ServiceLifetime.Scoped); /// @@ -94,7 +97,9 @@ public virtual IInternalServiceCollectionMap AddDependencyScoped( /// 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 IInternalServiceCollectionMap AddDependency(Type serviceType, ServiceLifetime lifetime) + public virtual IInternalServiceCollectionMap AddDependency( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType, + ServiceLifetime lifetime) { var indexes = GetOrCreateDescriptorIndexes(serviceType); if (!indexes.Any()) diff --git a/src/EFCore/Infrastructure/PooledDbContextFactory.cs b/src/EFCore/Infrastructure/PooledDbContextFactory.cs index 51bbb0e496c..773dcb66804 100644 --- a/src/EFCore/Infrastructure/PooledDbContextFactory.cs +++ b/src/EFCore/Infrastructure/PooledDbContextFactory.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; namespace Microsoft.EntityFrameworkCore.Infrastructure; @@ -20,7 +21,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure; /// Using DbContext pooling for more information and examples. /// /// -public class PooledDbContextFactory : IDbContextFactory +public class PooledDbContextFactory<[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext> + : IDbContextFactory where TContext : DbContext { private readonly IDbContextPool _pool; diff --git a/src/EFCore/Infrastructure/ServiceCollectionMap.cs b/src/EFCore/Infrastructure/ServiceCollectionMap.cs index 8e770230d0a..affce788bcb 100644 --- a/src/EFCore/Infrastructure/ServiceCollectionMap.cs +++ b/src/EFCore/Infrastructure/ServiceCollectionMap.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Infrastructure.Internal; namespace Microsoft.EntityFrameworkCore.Infrastructure; @@ -49,7 +50,8 @@ public virtual IServiceCollection ServiceCollection /// The contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddTransient() + public virtual ServiceCollectionMap TryAddTransient + () where TService : class where TImplementation : class, TService => TryAdd(typeof(TService), typeof(TImplementation), ServiceLifetime.Transient); @@ -61,7 +63,8 @@ public virtual ServiceCollectionMap TryAddTransient() /// The contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddScoped() + public virtual ServiceCollectionMap TryAddScoped + () where TService : class where TImplementation : class, TService => TryAdd(typeof(TService), typeof(TImplementation), ServiceLifetime.Scoped); @@ -73,7 +76,8 @@ public virtual ServiceCollectionMap TryAddScoped() /// The contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddSingleton() + public virtual ServiceCollectionMap TryAddSingleton + () where TService : class where TImplementation : class, TService => TryAdd(typeof(TService), typeof(TImplementation), ServiceLifetime.Singleton); @@ -85,7 +89,9 @@ public virtual ServiceCollectionMap TryAddSingleton() /// The contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddTransient(Type serviceType, Type implementationType) + public virtual ServiceCollectionMap TryAddTransient( + Type serviceType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) => TryAdd(serviceType, implementationType, ServiceLifetime.Transient); /// @@ -95,7 +101,9 @@ public virtual ServiceCollectionMap TryAddTransient(Type serviceType, Type imple /// The contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddScoped(Type serviceType, Type implementationType) + public virtual ServiceCollectionMap TryAddScoped( + Type serviceType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) => TryAdd(serviceType, implementationType, ServiceLifetime.Scoped); /// @@ -105,7 +113,9 @@ public virtual ServiceCollectionMap TryAddScoped(Type serviceType, Type implemen /// The contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddSingleton(Type serviceType, Type implementationType) + public virtual ServiceCollectionMap TryAddSingleton( + Type serviceType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) => TryAdd(serviceType, implementationType, ServiceLifetime.Singleton); /// @@ -118,7 +128,7 @@ public virtual ServiceCollectionMap TryAddSingleton(Type serviceType, Type imple /// The map, such that further calls can be chained. public virtual ServiceCollectionMap TryAdd( Type serviceType, - Type implementationType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime) { Validate?.Invoke(serviceType); @@ -300,7 +310,8 @@ public virtual ServiceCollectionMap TryAddSingleton(Type serviceType, object imp /// The contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddTransientEnumerable() + public virtual ServiceCollectionMap TryAddTransientEnumerable + () where TService : class where TImplementation : class, TService => TryAddEnumerable(typeof(TService), typeof(TImplementation), ServiceLifetime.Transient); @@ -313,7 +324,8 @@ public virtual ServiceCollectionMap TryAddTransientEnumerableThe contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddScopedEnumerable() + public virtual ServiceCollectionMap TryAddScopedEnumerable + () where TService : class where TImplementation : class, TService => TryAddEnumerable(typeof(TService), typeof(TImplementation), ServiceLifetime.Scoped); @@ -326,7 +338,8 @@ public virtual ServiceCollectionMap TryAddScopedEnumerableThe contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddSingletonEnumerable() + public virtual ServiceCollectionMap TryAddSingletonEnumerable + () where TService : class where TImplementation : class, TService => TryAddEnumerable(typeof(TService), typeof(TImplementation), ServiceLifetime.Singleton); @@ -339,7 +352,9 @@ public virtual ServiceCollectionMap TryAddSingletonEnumerableThe contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddTransientEnumerable(Type serviceType, Type implementationType) + public virtual ServiceCollectionMap TryAddTransientEnumerable( + Type serviceType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) => TryAddEnumerable(serviceType, implementationType, ServiceLifetime.Transient); /// @@ -350,7 +365,9 @@ public virtual ServiceCollectionMap TryAddTransientEnumerable(Type serviceType, /// The contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddScopedEnumerable(Type serviceType, Type implementationType) + public virtual ServiceCollectionMap TryAddScopedEnumerable( + Type serviceType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) => TryAddEnumerable(serviceType, implementationType, ServiceLifetime.Scoped); /// @@ -361,7 +378,9 @@ public virtual ServiceCollectionMap TryAddScopedEnumerable(Type serviceType, Typ /// The contract for the service. /// The concrete type that implements the service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddSingletonEnumerable(Type serviceType, Type implementationType) + public virtual ServiceCollectionMap TryAddSingletonEnumerable( + Type serviceType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) => TryAddEnumerable(serviceType, implementationType, ServiceLifetime.Singleton); /// @@ -375,7 +394,7 @@ public virtual ServiceCollectionMap TryAddSingletonEnumerable(Type serviceType, /// The map, such that further calls can be chained. public virtual ServiceCollectionMap TryAddEnumerable( Type serviceType, - Type implementationType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime) { Validate?.Invoke(serviceType); @@ -398,7 +417,9 @@ public virtual ServiceCollectionMap TryAddEnumerable( /// The concrete type that implements the service. /// The factory that implements this service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddTransientEnumerable( + public virtual ServiceCollectionMap TryAddTransientEnumerable< + TService, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>( Func factory) where TService : class where TImplementation : class, TService @@ -413,8 +434,9 @@ public virtual ServiceCollectionMap TryAddTransientEnumerableThe concrete type that implements the service. /// The factory that implements this service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddScopedEnumerable( - Func factory) + public virtual ServiceCollectionMap TryAddScopedEnumerable + ( + Func factory) where TService : class where TImplementation : class, TService => TryAddEnumerable(typeof(TService), typeof(TImplementation), factory, ServiceLifetime.Scoped); @@ -428,8 +450,9 @@ public virtual ServiceCollectionMap TryAddScopedEnumerableThe concrete type that implements the service. /// The factory that implements this service. /// The map, such that further calls can be chained. - public virtual ServiceCollectionMap TryAddSingletonEnumerable( - Func factory) + public virtual ServiceCollectionMap TryAddSingletonEnumerable + ( + Func factory) where TService : class where TImplementation : class, TService => TryAddEnumerable(typeof(TService), typeof(TImplementation), factory, ServiceLifetime.Singleton); @@ -446,7 +469,7 @@ public virtual ServiceCollectionMap TryAddSingletonEnumerableThe map, such that further calls can be chained. public virtual ServiceCollectionMap TryAddEnumerable( Type serviceType, - Type implementationType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, Func factory, ServiceLifetime lifetime) { diff --git a/src/EFCore/Internal/DbContextFactory.cs b/src/EFCore/Internal/DbContextFactory.cs index 9b17be0dca0..0d266e2c5c1 100644 --- a/src/EFCore/Internal/DbContextFactory.cs +++ b/src/EFCore/Internal/DbContextFactory.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Internal; /// @@ -9,7 +11,8 @@ namespace Microsoft.EntityFrameworkCore.Internal; /// 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 class DbContextFactory : IDbContextFactory +public class DbContextFactory<[DynamicallyAccessedMembers(DbContext.DynamicallyAccessedMemberTypes)] TContext> + : IDbContextFactory where TContext : DbContext { private readonly IServiceProvider _serviceProvider; diff --git a/src/EFCore/Internal/EntityFinderSource.cs b/src/EFCore/Internal/EntityFinderSource.cs index b1692e4e6dc..23e0822bb56 100644 --- a/src/EFCore/Internal/EntityFinderSource.cs +++ b/src/EFCore/Internal/EntityFinderSource.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; @@ -15,9 +16,6 @@ namespace Microsoft.EntityFrameworkCore.Internal; /// public class EntityFinderSource : IEntityFinderSource { - private static readonly MethodInfo GenericCreate - = typeof(EntityFinderSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateConstructor))!; - private readonly ConcurrentDictionary> _cache = new(); @@ -35,7 +33,8 @@ public virtual IEntityFinder Create( => _cache.GetOrAdd( type.ClrType, t => (Func) - GenericCreate.MakeGenericMethod(t).Invoke(null, null)!)(stateManager, setSource, setCache, type); + typeof(EntityFinderSource).GetMethod(nameof(CreateConstructor), BindingFlags.NonPublic | BindingFlags.Static)! + .MakeGenericMethod(t).Invoke(null, null)!)(stateManager, setSource, setCache, type); [UsedImplicitly] private static Func CreateConstructor() diff --git a/src/EFCore/Internal/IDbSetCache.cs b/src/EFCore/Internal/IDbSetCache.cs index 1057959c0fe..c16c6b97d9c 100644 --- a/src/EFCore/Internal/IDbSetCache.cs +++ b/src/EFCore/Internal/IDbSetCache.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; +using Microsoft.EntityFrameworkCore.Metadata.Internal; + namespace Microsoft.EntityFrameworkCore.Internal; /// @@ -17,7 +20,7 @@ public interface IDbSetCache /// 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 GetOrAddSet(IDbSetSource source, Type type); + object GetOrAddSet(IDbSetSource source, [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -25,7 +28,10 @@ public interface IDbSetCache /// 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 GetOrAddSet(IDbSetSource source, string entityTypeName, Type type); + object GetOrAddSet( + IDbSetSource source, + string entityTypeName, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Internal/IDbSetSource.cs b/src/EFCore/Internal/IDbSetSource.cs index fc6e8159cdb..8081768b320 100644 --- a/src/EFCore/Internal/IDbSetSource.cs +++ b/src/EFCore/Internal/IDbSetSource.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; +using Microsoft.EntityFrameworkCore.Metadata.Internal; + namespace Microsoft.EntityFrameworkCore.Internal; /// @@ -22,7 +25,9 @@ public interface IDbSetSource /// 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(DbContext context, Type type); + object Create( + DbContext context, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -30,5 +35,8 @@ public interface IDbSetSource /// 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(DbContext context, string name, Type type); + object Create( + DbContext context, + string name, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type); } diff --git a/src/EFCore/Internal/InternalDbSet.cs b/src/EFCore/Internal/InternalDbSet.cs index ff9d7c9c625..c5b954f07de 100644 --- a/src/EFCore/Internal/InternalDbSet.cs +++ b/src/EFCore/Internal/InternalDbSet.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; @@ -14,7 +15,7 @@ namespace Microsoft.EntityFrameworkCore.Internal; /// 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 class InternalDbSet : +public class InternalDbSet<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity> : DbSet, IQueryable, IAsyncEnumerable, diff --git a/src/EFCore/Metadata/Builders/CollectionCollectionBuilder`.cs b/src/EFCore/Metadata/Builders/CollectionCollectionBuilder`.cs index 7ce937d1a4b..9e8c73b1073 100644 --- a/src/EFCore/Metadata/Builders/CollectionCollectionBuilder`.cs +++ b/src/EFCore/Metadata/Builders/CollectionCollectionBuilder`.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// @@ -18,7 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// /// One of the entity types in this relationship. /// One of the entity types in this relationship. -public class CollectionCollectionBuilder : CollectionCollectionBuilder +public class CollectionCollectionBuilder< + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TLeftEntity, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRightEntity> : CollectionCollectionBuilder where TLeftEntity : class where TRightEntity : class { @@ -43,7 +47,8 @@ public CollectionCollectionBuilder( /// /// The CLR type of the join entity. /// The builder for the join entity type. - public virtual EntityTypeBuilder UsingEntity() + public virtual EntityTypeBuilder UsingEntity + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TJoinEntity>() where TJoinEntity : class => Using(joinEntityName: null, configureRight: null, configureLeft: null); @@ -53,8 +58,8 @@ public virtual EntityTypeBuilder UsingEntity() /// The name of the join entity. /// The CLR type of the join entity. /// The builder for the join entity type. - public virtual EntityTypeBuilder UsingEntity( - string joinEntityName) + public virtual EntityTypeBuilder UsingEntity + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TJoinEntity>(string joinEntityName) where TJoinEntity : class { Check.NotEmpty(joinEntityName, nameof(joinEntityName)); @@ -125,7 +130,7 @@ public virtual EntityTypeBuilder UsingEntity( /// The builder for the originating entity type so that multiple configuration calls can be chained. public new virtual EntityTypeBuilder UsingEntity( string joinEntityName, - Type joinEntityType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type joinEntityType, Action configureJoinEntityType) { Check.NotNull(configureJoinEntityType, nameof(configureJoinEntityType)); @@ -141,8 +146,9 @@ public virtual EntityTypeBuilder UsingEntity( /// The configuration of the join entity type. /// The CLR type of the join entity. /// The builder for the originating entity type so that multiple configuration calls can be chained. - public virtual EntityTypeBuilder UsingEntity( - Action> configureJoinEntityType) + public virtual EntityTypeBuilder UsingEntity + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TJoinEntity>( + Action> configureJoinEntityType) where TJoinEntity : class { Check.NotNull(configureJoinEntityType, nameof(configureJoinEntityType)); @@ -160,9 +166,10 @@ public virtual EntityTypeBuilder UsingEntity( /// The configuration of the join entity type. /// The CLR type of the join entity. /// The builder for the originating entity type so that multiple configuration calls can be chained. - public virtual EntityTypeBuilder UsingEntity( - string joinEntityName, - Action> configureJoinEntityType) + public virtual EntityTypeBuilder UsingEntity + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TJoinEntity>( + string joinEntityName, + Action> configureJoinEntityType) where TJoinEntity : class { Check.NotNull(configureJoinEntityType, nameof(configureJoinEntityType)); @@ -180,9 +187,10 @@ public virtual EntityTypeBuilder UsingEntity( /// The configuration for the relationship to the left entity type. /// The CLR type of the join entity. /// The builder for the join type. - public virtual EntityTypeBuilder UsingEntity( - Func, ReferenceCollectionBuilder> configureRight, - Func, ReferenceCollectionBuilder> configureLeft) + public virtual EntityTypeBuilder UsingEntity + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TJoinEntity>( + Func, ReferenceCollectionBuilder> configureRight, + Func, ReferenceCollectionBuilder> configureLeft) where TJoinEntity : class { Check.NotNull(configureRight, nameof(configureRight)); @@ -199,10 +207,11 @@ public virtual EntityTypeBuilder UsingEntity( /// The configuration for the relationship to the left entity type. /// The CLR type of the join entity. /// The builder for the join entity type. - public virtual EntityTypeBuilder UsingEntity( - string joinEntityName, - Func, ReferenceCollectionBuilder> configureRight, - Func, ReferenceCollectionBuilder> configureLeft) + public virtual EntityTypeBuilder UsingEntity + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TJoinEntity>( + string joinEntityName, + Func, ReferenceCollectionBuilder> configureRight, + Func, ReferenceCollectionBuilder> configureLeft) where TJoinEntity : class { Check.NotEmpty(joinEntityName, nameof(joinEntityName)); @@ -240,7 +249,7 @@ public virtual EntityTypeBuilder UsingEntity( /// The configuration of the join entity type. /// The builder for the originating entity type so that multiple configuration calls can be chained. public new virtual EntityTypeBuilder UsingEntity( - Type joinEntityType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type joinEntityType, Func configureRight, Func configureLeft, Action configureJoinEntityType) @@ -284,7 +293,7 @@ public virtual EntityTypeBuilder UsingEntity( /// The builder for the originating entity type so that multiple configuration calls can be chained. public new virtual EntityTypeBuilder UsingEntity( string joinEntityName, - Type joinEntityType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type joinEntityType, Func configureRight, Func configureLeft, Action configureJoinEntityType) @@ -304,10 +313,11 @@ public virtual EntityTypeBuilder UsingEntity( /// The configuration of the join entity type. /// The CLR type of the join entity. /// The builder for the originating entity type so that multiple configuration calls can be chained. - public virtual EntityTypeBuilder UsingEntity( - Func, ReferenceCollectionBuilder> configureRight, - Func, ReferenceCollectionBuilder> configureLeft, - Action> configureJoinEntityType) + public virtual EntityTypeBuilder UsingEntity + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TJoinEntity>( + Func, ReferenceCollectionBuilder> configureRight, + Func, ReferenceCollectionBuilder> configureLeft, + Action> configureJoinEntityType) where TJoinEntity : class { Check.NotNull(configureJoinEntityType, nameof(configureJoinEntityType)); @@ -327,7 +337,8 @@ public virtual EntityTypeBuilder UsingEntity( /// The configuration of the join entity type. /// The CLR type of the join entity. /// The builder for the originating entity type so that multiple configuration calls can be chained. - public virtual EntityTypeBuilder UsingEntity( + public virtual EntityTypeBuilder UsingEntity< + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TJoinEntity>( string joinEntityName, Func, ReferenceCollectionBuilder> configureRight, Func, ReferenceCollectionBuilder> configureLeft, @@ -342,7 +353,7 @@ public virtual EntityTypeBuilder UsingEntity( return new EntityTypeBuilder(RightEntityType); } - private EntityTypeBuilder Using( + private EntityTypeBuilder Using<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TJoinEntity>( string? joinEntityName, Func, ReferenceCollectionBuilder>? configureRight, Func, ReferenceCollectionBuilder>? configureLeft) diff --git a/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs b/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs index cada562e358..1a7ae5acc66 100644 --- a/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs +++ b/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// @@ -16,7 +18,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// /// The entity type to be configured. /// The entity type that this relationship targets. -public class CollectionNavigationBuilder : CollectionNavigationBuilder +public class CollectionNavigationBuilder< + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity> : CollectionNavigationBuilder where TEntity : class where TRelatedEntity : class { diff --git a/src/EFCore/Metadata/Builders/DiscriminatorBuilder.cs b/src/EFCore/Metadata/Builders/DiscriminatorBuilder.cs index b7c993fc86e..a53a76aa58b 100644 --- a/src/EFCore/Metadata/Builders/DiscriminatorBuilder.cs +++ b/src/EFCore/Metadata/Builders/DiscriminatorBuilder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Metadata.Builders; @@ -79,7 +80,8 @@ public virtual DiscriminatorBuilder HasValue(object? value) /// The entity type for which a discriminator value is being set. /// The discriminator value. /// The same builder so that multiple calls can be chained. - public virtual DiscriminatorBuilder HasValue(object? value) + public virtual DiscriminatorBuilder HasValue<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>( + object? value) => HasValue(typeof(TEntity), value); /// @@ -88,7 +90,9 @@ public virtual DiscriminatorBuilder HasValue(object? value) /// The entity type for which a discriminator value is being set. /// The discriminator value. /// The same builder so that multiple calls can be chained. - public virtual DiscriminatorBuilder HasValue(Type entityType, object? value) + public virtual DiscriminatorBuilder HasValue( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type entityType, + object? value) { var entityTypeBuilder = EntityTypeBuilder.ModelBuilder.Entity( entityType, ConfigurationSource.Explicit); diff --git a/src/EFCore/Metadata/Builders/DiscriminatorBuilder`.cs b/src/EFCore/Metadata/Builders/DiscriminatorBuilder`.cs index cf81f10e163..26ceb9e2bde 100644 --- a/src/EFCore/Metadata/Builders/DiscriminatorBuilder`.cs +++ b/src/EFCore/Metadata/Builders/DiscriminatorBuilder`.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// @@ -48,7 +50,8 @@ public virtual DiscriminatorBuilder HasValue(TDiscriminator valu /// The entity type for which a discriminator value is being set. /// The discriminator value. /// The same builder so that multiple calls can be chained. - public virtual DiscriminatorBuilder HasValue(TDiscriminator value) + public virtual DiscriminatorBuilder HasValue + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>(TDiscriminator value) => HasValue(typeof(TEntity), value); /// @@ -57,7 +60,9 @@ public virtual DiscriminatorBuilder HasValue(TDiscrimin /// The entity type for which a discriminator value is being set. /// The discriminator value. /// The same builder so that multiple calls can be chained. - public virtual DiscriminatorBuilder HasValue(Type entityType, TDiscriminator value) + public virtual DiscriminatorBuilder HasValue( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type entityType, + TDiscriminator value) => new(Builder.HasValue(entityType, value)); /// diff --git a/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs b/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs index 1b3a54b293a..4937b1b67ee 100644 --- a/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Metadata.Builders; @@ -173,7 +174,8 @@ public virtual PropertyBuilder Property(Type propertyType, string propertyName) /// The type of the property to be configured. /// The name of the property to be configured. /// An object that can be used to configure the property. - public virtual PropertyBuilder IndexerProperty(string propertyName) + public virtual PropertyBuilder IndexerProperty + <[DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] TProperty>(string propertyName) => new( Builder.IndexerProperty( typeof(TProperty), @@ -191,11 +193,17 @@ public virtual PropertyBuilder IndexerProperty(string prop /// The type of the property to be configured. /// The name of the property to be configured. /// An object that can be used to configure the property. - public virtual PropertyBuilder IndexerProperty(Type propertyType, string propertyName) - => new( + public virtual PropertyBuilder IndexerProperty( + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, + string propertyName) + { + Check.NotNull(propertyType, nameof(propertyType)); + + return new( Builder.IndexerProperty( - Check.NotNull(propertyType, nameof(propertyType)), + propertyType, Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!.Metadata); + } /// /// Returns an object that can be used to configure an existing navigation property of the entity type. @@ -315,7 +323,7 @@ public virtual OwnedNavigationBuilder OwnsOne( /// An object that can be used to configure the owned type and the relationship. public virtual OwnedNavigationBuilder OwnsOne( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName) => OwnsOneBuilder( new TypeIdentity(Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)), ownedType), @@ -344,11 +352,15 @@ public virtual OwnedNavigationBuilder OwnsOne( /// /// An object that can be used to configure the owned type and the relationship. public virtual OwnedNavigationBuilder OwnsOne( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName) - => OwnsOneBuilder( - new TypeIdentity(Check.NotNull(ownedType, nameof(ownedType)), (Model)Metadata.Model), + { + Check.NotNull(ownedType, nameof(ownedType)); + + return OwnsOneBuilder( + new TypeIdentity(ownedType, (Model)Metadata.Model), Check.NotEmpty(navigationName, nameof(navigationName))); + } /// /// Configures a relationship where the target entity is owned by (or part of) this entity. @@ -412,7 +424,7 @@ public virtual EntityTypeBuilder OwnsOne( /// An object that can be used to configure the entity type. public virtual EntityTypeBuilder OwnsOne( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) { @@ -449,7 +461,7 @@ public virtual EntityTypeBuilder OwnsOne( /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. public virtual EntityTypeBuilder OwnsOne( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) { @@ -529,11 +541,15 @@ public virtual OwnedNavigationBuilder OwnsMany( /// An object that can be used to configure the owned type and the relationship. public virtual OwnedNavigationBuilder OwnsMany( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName) - => OwnsManyBuilder( - new TypeIdentity(Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)), Check.NotNull(ownedType, nameof(ownedType))), + { + Check.NotNull(ownedType, nameof(ownedType)); + + return OwnsManyBuilder( + new TypeIdentity(Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)), ownedType), Check.NotEmpty(navigationName, nameof(navigationName))); + } /// /// Configures a relationship where the target entity is owned by (or part of) this entity. @@ -558,11 +574,15 @@ public virtual OwnedNavigationBuilder OwnsMany( /// /// An object that can be used to configure the owned type and the relationship. public virtual OwnedNavigationBuilder OwnsMany( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName) - => OwnsManyBuilder( - new TypeIdentity(Check.NotNull(ownedType, nameof(ownedType)), (Model)Metadata.Model), + { + Check.NotNull(ownedType, nameof(ownedType)); + + return OwnsManyBuilder( + new TypeIdentity(ownedType, (Model)Metadata.Model), Check.NotEmpty(navigationName, nameof(navigationName))); + } /// /// Configures a relationship where the target entity is owned by (or part of) this entity. @@ -626,7 +646,7 @@ public virtual EntityTypeBuilder OwnsMany( /// An object that can be used to configure the entity type. public virtual EntityTypeBuilder OwnsMany( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) { @@ -663,7 +683,7 @@ public virtual EntityTypeBuilder OwnsMany( /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. public virtual EntityTypeBuilder OwnsMany( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) { @@ -758,7 +778,7 @@ public virtual ReferenceNavigationBuilder HasOne( /// /// An object that can be used to configure the relationship. public virtual ReferenceNavigationBuilder HasOne( - Type relatedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type relatedType, string? navigationName = null) { Check.NotNull(relatedType, nameof(relatedType)); @@ -791,6 +811,7 @@ public virtual ReferenceNavigationBuilder HasOne( /// the relationship. The navigation must be a CLR property on the entity type. /// /// An object that can be used to configure the relationship. + [RequiresUnreferencedCode("Use an overload that accepts a type")] public virtual ReferenceNavigationBuilder HasOne(string? navigationName) { Check.NotEmpty(navigationName, nameof(navigationName)); @@ -872,6 +893,7 @@ public virtual CollectionNavigationBuilder HasMany( /// The navigation must be a CLR property on the entity type. /// /// An object that can be used to configure the relationship. + [RequiresUnreferencedCode("Use the generic overload instead")] public virtual CollectionNavigationBuilder HasMany(string navigationName) { Check.NotEmpty(navigationName, nameof(navigationName)); @@ -917,7 +939,7 @@ public virtual CollectionNavigationBuilder HasMany(string navigationName) /// /// An object that can be used to configure the relationship. public virtual CollectionNavigationBuilder HasMany( - Type relatedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type relatedType, string? navigationName = null) { Check.NotNull(relatedType, nameof(relatedType)); @@ -974,7 +996,9 @@ protected virtual EntityType FindRelatedEntityType(string relatedTypeName, strin /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [EntityFrameworkInternal] - protected virtual EntityType FindRelatedEntityType(Type relatedType, string? navigationName) + protected virtual EntityType FindRelatedEntityType( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type relatedType, + string? navigationName) => (navigationName == null || !Builder.ModelBuilder.Metadata.IsShared(relatedType) ? null : Builder.ModelBuilder.Metadata.FindEntityType(relatedType, navigationName, Builder.Metadata)) diff --git a/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs b/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs index 07b0f172faf..1f2c5ae82d2 100644 --- a/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs +++ b/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Metadata.Builders; @@ -16,7 +17,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// See Modeling entity types and relationships for more information and examples. /// /// The entity type being configured. -public class EntityTypeBuilder : EntityTypeBuilder +public class EntityTypeBuilder<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity> : EntityTypeBuilder where TEntity : class { /// @@ -338,8 +339,8 @@ public virtual IndexBuilder HasIndex( /// The name of the reference navigation property on this entity type that represents the relationship. /// /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsOne( - string navigationName) + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>(string navigationName) where TRelatedEntity : class => OwnsOneBuilder( new TypeIdentity(typeof(TRelatedEntity), (Model)Metadata.Model), @@ -368,9 +369,10 @@ public virtual OwnedNavigationBuilder OwnsOne /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsOne( - string ownedTypeName, - string navigationName) + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string ownedTypeName, + string navigationName) where TRelatedEntity : class => OwnsOneBuilder( new TypeIdentity(Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)), typeof(TRelatedEntity)), @@ -399,7 +401,8 @@ public virtual OwnedNavigationBuilder OwnsOnecustomer => customer.Address). /// /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsOne( + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( Expression> navigationExpression) where TRelatedEntity : class => OwnsOneBuilder( @@ -430,9 +433,10 @@ public virtual OwnedNavigationBuilder OwnsOnecustomer => customer.Address). /// /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsOne( - string ownedTypeName, - Expression> navigationExpression) + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string ownedTypeName, + Expression> navigationExpression) where TRelatedEntity : class => OwnsOneBuilder( new TypeIdentity(Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)), typeof(TRelatedEntity)), @@ -461,9 +465,10 @@ public virtual OwnedNavigationBuilder OwnsOne /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder OwnsOne( - string navigationName, - Action> buildAction) + public virtual EntityTypeBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string navigationName, + Action> buildAction) where TRelatedEntity : class { Check.NotEmpty(navigationName, nameof(navigationName)); @@ -528,7 +533,7 @@ public virtual EntityTypeBuilder OwnsOne( /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. public new virtual EntityTypeBuilder OwnsOne( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) => (EntityTypeBuilder)base.OwnsOne(ownedType, navigationName, buildAction); @@ -559,7 +564,7 @@ public virtual EntityTypeBuilder OwnsOne( /// An object that can be used to configure the entity type. public new virtual EntityTypeBuilder OwnsOne( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) => (EntityTypeBuilder)base.OwnsOne(ownedTypeName, ownedType, navigationName, buildAction); @@ -588,10 +593,11 @@ public virtual EntityTypeBuilder OwnsOne( /// /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder OwnsOne( - string ownedTypeName, - string navigationName, - Action> buildAction) + public virtual EntityTypeBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string ownedTypeName, + string navigationName, + Action> buildAction) where TRelatedEntity : class { Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)); @@ -628,9 +634,10 @@ public virtual EntityTypeBuilder OwnsOne( /// /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder OwnsOne( - Expression> navigationExpression, - Action> buildAction) + public virtual EntityTypeBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + Expression> navigationExpression, + Action> buildAction) where TRelatedEntity : class { Check.NotNull(navigationExpression, nameof(navigationExpression)); @@ -668,10 +675,11 @@ public virtual EntityTypeBuilder OwnsOne( /// /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder OwnsOne( - string ownedTypeName, - Expression> navigationExpression, - Action> buildAction) + public virtual EntityTypeBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string ownedTypeName, + Expression> navigationExpression, + Action> buildAction) where TRelatedEntity : class { Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)); @@ -684,9 +692,10 @@ public virtual EntityTypeBuilder OwnsOne( return this; } - private OwnedNavigationBuilder OwnsOneBuilder( - TypeIdentity ownedType, - MemberIdentity navigation) + private OwnedNavigationBuilder OwnsOneBuilder + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + TypeIdentity ownedType, + MemberIdentity navigation) where TRelatedEntity : class { InternalForeignKeyBuilder relationship; @@ -722,8 +731,9 @@ private OwnedNavigationBuilder OwnsOneBuilder /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsMany( - string navigationName) + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string navigationName) where TRelatedEntity : class => OwnsManyBuilder( new TypeIdentity(typeof(TRelatedEntity), (Model)Metadata.Model), @@ -752,9 +762,10 @@ public virtual OwnedNavigationBuilder OwnsMany /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsMany( - string ownedTypeName, - string navigationName) + public virtual OwnedNavigationBuilder + OwnsMany<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string ownedTypeName, + string navigationName) where TRelatedEntity : class => OwnsManyBuilder( new TypeIdentity(ownedTypeName, typeof(TRelatedEntity)), @@ -783,8 +794,9 @@ public virtual OwnedNavigationBuilder OwnsManycustomer => customer.Address). /// /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsMany( - Expression?>> navigationExpression) + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + Expression?>> navigationExpression) where TRelatedEntity : class => OwnsManyBuilder( new TypeIdentity(typeof(TRelatedEntity), (Model)Metadata.Model), @@ -814,9 +826,10 @@ public virtual OwnedNavigationBuilder OwnsManycustomer => customer.Address). /// /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsMany( - string ownedTypeName, - Expression?>> navigationExpression) + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string ownedTypeName, + Expression?>> navigationExpression) where TRelatedEntity : class => OwnsManyBuilder( new TypeIdentity(ownedTypeName, typeof(TRelatedEntity)), @@ -845,9 +858,10 @@ public virtual OwnedNavigationBuilder OwnsMany /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder OwnsMany( - string navigationName, - Action> buildAction) + public virtual EntityTypeBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string navigationName, + Action> buildAction) where TRelatedEntity : class { Check.NotEmpty(navigationName, nameof(navigationName)); @@ -912,7 +926,7 @@ public virtual EntityTypeBuilder OwnsMany( /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. public new virtual EntityTypeBuilder OwnsMany( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) => (EntityTypeBuilder)base.OwnsMany(ownedType, navigationName, buildAction); @@ -943,7 +957,7 @@ public virtual EntityTypeBuilder OwnsMany( /// An object that can be used to configure the entity type. public new virtual EntityTypeBuilder OwnsMany( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) => (EntityTypeBuilder)base.OwnsMany(ownedTypeName, ownedType, navigationName, buildAction); @@ -972,10 +986,11 @@ public virtual EntityTypeBuilder OwnsMany( /// /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder OwnsMany( - string ownedTypeName, - string navigationName, - Action> buildAction) + public virtual EntityTypeBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string ownedTypeName, + string navigationName, + Action> buildAction) where TRelatedEntity : class { Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)); @@ -1012,9 +1027,10 @@ public virtual EntityTypeBuilder OwnsMany( /// /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder OwnsMany( - Expression?>> navigationExpression, - Action> buildAction) + public virtual EntityTypeBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + Expression?>> navigationExpression, + Action> buildAction) where TRelatedEntity : class { Check.NotNull(navigationExpression, nameof(navigationExpression)); @@ -1052,10 +1068,11 @@ public virtual EntityTypeBuilder OwnsMany( /// /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder OwnsMany( - string ownedTypeName, - Expression?>> navigationExpression, - Action> buildAction) + public virtual EntityTypeBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string ownedTypeName, + Expression?>> navigationExpression, + Action> buildAction) where TRelatedEntity : class { Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)); @@ -1068,9 +1085,10 @@ public virtual EntityTypeBuilder OwnsMany( return this; } - private OwnedNavigationBuilder OwnsManyBuilder( - TypeIdentity ownedType, - MemberIdentity navigation) + private OwnedNavigationBuilder OwnsManyBuilder + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + TypeIdentity ownedType, + MemberIdentity navigation) where TRelatedEntity : class { InternalForeignKeyBuilder relationship; @@ -1111,8 +1129,9 @@ private OwnedNavigationBuilder OwnsManyBuilder /// An object that can be used to configure the relationship. - public virtual ReferenceNavigationBuilder HasOne( - string? navigationName) + public virtual ReferenceNavigationBuilder HasOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + string? navigationName) where TRelatedEntity : class { var relatedEntityType = FindRelatedEntityType(typeof(TRelatedEntity), navigationName); @@ -1154,8 +1173,9 @@ public virtual ReferenceNavigationBuilder HasOne /// An object that can be used to configure the relationship. - public virtual ReferenceNavigationBuilder HasOne( - Expression>? navigationExpression = null) + public virtual ReferenceNavigationBuilder HasOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( + Expression>? navigationExpression = null) where TRelatedEntity : class { var navigationMember = navigationExpression?.GetMemberAccess(); @@ -1195,8 +1215,8 @@ public virtual ReferenceNavigationBuilder HasOne /// An object that can be used to configure the relationship. - public virtual CollectionNavigationBuilder HasMany( - string? navigationName) + public virtual CollectionNavigationBuilder HasMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>(string? navigationName) where TRelatedEntity : class { Check.NullButNotEmpty(navigationName, nameof(navigationName)); @@ -1250,7 +1270,8 @@ public virtual CollectionNavigationBuilder HasMany /// An object that can be used to configure the relationship. - public virtual CollectionNavigationBuilder HasMany( + public virtual CollectionNavigationBuilder HasMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TRelatedEntity>( Expression?>>? navigationExpression = null) where TRelatedEntity : class { diff --git a/src/EFCore/Metadata/Builders/IConventionModelBuilder.cs b/src/EFCore/Metadata/Builders/IConventionModelBuilder.cs index 9d00d9d8e7b..a8fcea58cb0 100644 --- a/src/EFCore/Metadata/Builders/IConventionModelBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionModelBuilder.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// @@ -65,7 +67,7 @@ public interface IConventionModelBuilder : IConventionAnnotatableBuilder /// IConventionEntityTypeBuilder? SharedTypeEntity( string name, - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, bool? shouldBeOwned = false, bool fromDataAnnotation = false); @@ -84,7 +86,10 @@ public interface IConventionModelBuilder : IConventionAnnotatableBuilder /// An object that can be used to configure the entity type if the entity type was added or already part of the model, /// otherwise. /// - IConventionEntityTypeBuilder? Entity(Type type, bool? shouldBeOwned = false, bool fromDataAnnotation = false); + IConventionEntityTypeBuilder? Entity( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool? shouldBeOwned = false, + bool fromDataAnnotation = false); /// /// Returns an object that can be used to configure a given entity type with defining navigation. @@ -119,7 +124,7 @@ public interface IConventionModelBuilder : IConventionAnnotatableBuilder /// otherwise. /// IConventionEntityTypeBuilder? Entity( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, string definingNavigationName, IConventionEntityType definingEntityType, bool fromDataAnnotation = false); @@ -133,7 +138,9 @@ public interface IConventionModelBuilder : IConventionAnnotatableBuilder /// /// An object that can be used to provide default configuration for the owned entity types. /// - IConventionOwnedEntityTypeBuilder? Owned(Type type, bool fromDataAnnotation = false); + IConventionOwnedEntityTypeBuilder? Owned( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation = false); /// /// Indicates whether the given entity type name is ignored for the current configuration source. @@ -141,7 +148,7 @@ public interface IConventionModelBuilder : IConventionAnnotatableBuilder /// The name of the entity type that might be ignored. /// Indicates whether the configuration was specified using a data annotation. /// if the given entity type name is ignored. - bool IsIgnored(Type type, bool fromDataAnnotation = false); + bool IsIgnored([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, bool fromDataAnnotation = false); /// /// Indicates whether the given entity type name is ignored for the current configuration source. @@ -160,7 +167,9 @@ public interface IConventionModelBuilder : IConventionAnnotatableBuilder /// The same builder instance so that additional configuration calls can be chained /// if the given entity type was ignored, otherwise. /// - IConventionModelBuilder? Ignore(Type type, bool fromDataAnnotation = false); + IConventionModelBuilder? Ignore( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation = false); /// /// Excludes the given entity type name from the model and prevents it from being added by convention. @@ -189,7 +198,7 @@ public interface IConventionModelBuilder : IConventionAnnotatableBuilder /// The entity type to be removed from the model. /// Indicates whether the configuration was specified using a data annotation. /// if the given entity type can be ignored. - bool CanIgnore(Type type, bool fromDataAnnotation = false); + bool CanIgnore([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, bool fromDataAnnotation = false); /// /// Returns a value indicating whether the given entity type name can be ignored from the current configuration source diff --git a/src/EFCore/Metadata/Builders/IConventionPropertyBuilder.cs b/src/EFCore/Metadata/Builders/IConventionPropertyBuilder.cs index beeb081763f..49f9953fdb1 100644 --- a/src/EFCore/Metadata/Builders/IConventionPropertyBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionPropertyBuilder.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// @@ -282,7 +284,9 @@ public interface IConventionPropertyBuilder : IConventionPropertyBaseBuilder /// The same builder instance if the configuration was applied, /// otherwise. /// - IConventionPropertyBuilder? HasValueGenerator(Type? valueGeneratorType, bool fromDataAnnotation = false); + IConventionPropertyBuilder? HasValueGenerator( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? valueGeneratorType, + bool fromDataAnnotation = false); /// /// Configures the that will generate values for this property. @@ -307,7 +311,9 @@ public interface IConventionPropertyBuilder : IConventionPropertyBaseBuilder /// The same builder instance if the configuration was applied, /// otherwise. /// - IConventionPropertyBuilder? HasValueGeneratorFactory(Type? valueGeneratorFactoryType, bool fromDataAnnotation = false); + IConventionPropertyBuilder? HasValueGeneratorFactory( + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? valueGeneratorFactoryType, + bool fromDataAnnotation = false); /// /// Returns a value indicating whether the can be configured for this property @@ -340,7 +346,7 @@ bool CanSetValueGenerator( /// if the can be configured for this property. /// bool CanSetValueGeneratorFactory( - Type? valueGeneratorFactoryType, + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? valueGeneratorFactoryType, bool fromDataAnnotation = false); /// @@ -402,7 +408,9 @@ bool CanSetValueGeneratorFactory( /// The same builder instance if the configuration was applied, /// otherwise. /// - IConventionPropertyBuilder? HasConverter(Type? converterType, bool fromDataAnnotation = false); + IConventionPropertyBuilder? HasConverter( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType, + bool fromDataAnnotation = false); /// /// Returns a value indicating whether the can be configured for this property @@ -416,7 +424,7 @@ bool CanSetValueGeneratorFactory( /// /// if the can be configured for this property. /// - bool CanSetConverter(Type? converterType, bool fromDataAnnotation = false); + bool CanSetConverter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType, bool fromDataAnnotation = false); /// /// Configures the for this property. @@ -472,7 +480,9 @@ bool CanSetValueGeneratorFactory( /// /// The same builder instance if the configuration was applied, otherwise. /// - IConventionPropertyBuilder? HasValueComparer(Type? comparerType, bool fromDataAnnotation = false); + IConventionPropertyBuilder? HasValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation = false); /// /// Returns a value indicating whether the given @@ -486,7 +496,9 @@ bool CanSetValueGeneratorFactory( /// /// if the given can be configured for this property. /// - bool CanSetValueComparer(Type? comparerType, bool fromDataAnnotation = false); + bool CanSetValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation = false); /// /// Configures the to use for the provider values for this property. @@ -520,7 +532,9 @@ bool CanSetValueGeneratorFactory( /// /// The same builder instance if the configuration was applied, otherwise. /// - IConventionPropertyBuilder? HasProviderValueComparer(Type? comparerType, bool fromDataAnnotation = false); + IConventionPropertyBuilder? HasProviderValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation = false); /// /// Returns a value indicating whether the given @@ -534,5 +548,7 @@ bool CanSetValueGeneratorFactory( /// /// if the given can be configured for this property. /// - bool CanSetProviderValueComparer(Type? comparerType, bool fromDataAnnotation = false); + bool CanSetProviderValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation = false); } diff --git a/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs b/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs index aba20203604..d86b245d5fe 100644 --- a/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs +++ b/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Metadata.Builders; @@ -202,7 +203,8 @@ public virtual PropertyBuilder Property(Type propertyType, string propertyName) /// The type of the property to be configured. /// The name of the property to be configured. /// An object that can be used to configure the property. - public virtual PropertyBuilder IndexerProperty(string propertyName) + public virtual PropertyBuilder IndexerProperty + <[DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] TProperty>(string propertyName) => new( DependentEntityType.Builder.IndexerProperty( typeof(TProperty), @@ -220,11 +222,17 @@ public virtual PropertyBuilder IndexerProperty(string prop /// The type of the property to be configured. /// The name of the property to be configured. /// An object that can be used to configure the property. - public virtual PropertyBuilder IndexerProperty(Type propertyType, string propertyName) - => new( + public virtual PropertyBuilder IndexerProperty( + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, + string propertyName) + { + Check.NotNull(propertyType, nameof(propertyType)); + + return new( DependentEntityType.Builder.IndexerProperty( - Check.NotNull(propertyType, nameof(propertyType)), + propertyType, Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!.Metadata); + } /// /// Returns an object that can be used to configure an existing navigation property @@ -346,11 +354,15 @@ public virtual OwnedNavigationBuilder OwnsOne( /// An object that can be used to configure the relationship. public virtual OwnedNavigationBuilder OwnsOne( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName) - => OwnsOneBuilder( - new TypeIdentity(Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)), Check.NotNull(ownedType, nameof(ownedType))), + { + Check.NotNull(ownedType, nameof(ownedType)); + + return OwnsOneBuilder( + new TypeIdentity(Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)), ownedType), Check.NotEmpty(navigationName, nameof(navigationName))); + } /// /// Configures a relationship where the target entity is owned by (or part of) this entity. @@ -376,11 +388,15 @@ public virtual OwnedNavigationBuilder OwnsOne( /// /// An object that can be used to configure the relationship. public virtual OwnedNavigationBuilder OwnsOne( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName) - => OwnsOneBuilder( - new TypeIdentity(Check.NotNull(ownedType, nameof(ownedType)), DependentEntityType.Model), + { + Check.NotNull(ownedType, nameof(ownedType)); + + return OwnsOneBuilder( + new TypeIdentity(ownedType, DependentEntityType.Model), Check.NotEmpty(navigationName, nameof(navigationName))); + } /// /// Configures a relationship where the target entity is owned by (or part of) this entity. @@ -449,7 +465,7 @@ public virtual OwnedNavigationBuilder OwnsOne( /// An object that can be used to configure the entity type. public virtual OwnedNavigationBuilder OwnsOne( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) { @@ -490,7 +506,7 @@ public virtual OwnedNavigationBuilder OwnsOne( /// An action that performs configuration of the relationship. /// An object that can be used to configure the entity type. public virtual OwnedNavigationBuilder OwnsOne( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) { @@ -573,11 +589,15 @@ public virtual OwnedNavigationBuilder OwnsMany( /// An object that can be used to configure the owned type and the relationship. public virtual OwnedNavigationBuilder OwnsMany( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName) - => OwnsManyBuilder( - new TypeIdentity(Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)), Check.NotNull(ownedType, nameof(ownedType))), + { + Check.NotNull(ownedType, nameof(ownedType)); + + return OwnsManyBuilder( + new TypeIdentity(Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)), ownedType), Check.NotEmpty(navigationName, nameof(navigationName))); + } /// /// Configures a relationship where the target entity is owned by (or part of) this entity. @@ -602,11 +622,15 @@ public virtual OwnedNavigationBuilder OwnsMany( /// /// An object that can be used to configure the owned type and the relationship. public virtual OwnedNavigationBuilder OwnsMany( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName) - => OwnsManyBuilder( - new TypeIdentity(Check.NotNull(ownedType, nameof(ownedType)), DependentEntityType.Model), + { + Check.NotNull(ownedType, nameof(ownedType)); + + return OwnsManyBuilder( + new TypeIdentity(ownedType, DependentEntityType.Model), Check.NotEmpty(navigationName, nameof(navigationName))); + } /// /// Configures a relationship where the target entity is owned by (or part of) this entity. @@ -673,7 +697,7 @@ public virtual OwnedNavigationBuilder OwnsMany( /// An object that can be used to configure the entity type. public virtual OwnedNavigationBuilder OwnsMany( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) { @@ -713,7 +737,7 @@ public virtual OwnedNavigationBuilder OwnsMany( /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. public virtual OwnedNavigationBuilder OwnsMany( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) { @@ -807,6 +831,7 @@ public virtual ReferenceNavigationBuilder HasOne( /// The name of the reference navigation property on this entity type that represents the relationship. /// /// An object that can be used to configure the relationship. + [RequiresUnreferencedCode("Use an overload that accepts a type")] public virtual ReferenceNavigationBuilder HasOne(string navigationName) { Check.NotEmpty(navigationName, nameof(navigationName)); @@ -842,7 +867,7 @@ public virtual ReferenceNavigationBuilder HasOne(string navigationName) /// /// An object that can be used to configure the relationship. public virtual ReferenceNavigationBuilder HasOne( - Type relatedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type relatedType, string? navigationName = null) { Check.NotNull(relatedType, nameof(relatedType)); @@ -900,7 +925,9 @@ protected virtual EntityType FindRelatedEntityType(string relatedTypeName, strin /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [EntityFrameworkInternal] - protected virtual EntityType FindRelatedEntityType(Type relatedType, string? navigationName) + protected virtual EntityType FindRelatedEntityType( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type relatedType, + string? navigationName) { var relatedEntityType = (EntityType?)DependentEntityType.FindInOwnershipPath(relatedType); if (relatedEntityType != null) diff --git a/src/EFCore/Metadata/Builders/OwnedNavigationBuilder`.cs b/src/EFCore/Metadata/Builders/OwnedNavigationBuilder`.cs index bb70a5e12c3..9168293a31a 100644 --- a/src/EFCore/Metadata/Builders/OwnedNavigationBuilder`.cs +++ b/src/EFCore/Metadata/Builders/OwnedNavigationBuilder`.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Metadata.Builders; @@ -11,7 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// /// See Modeling entity types and relationships for more information and examples. /// -public class OwnedNavigationBuilder : OwnedNavigationBuilder +public class OwnedNavigationBuilder< + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TOwnerEntity, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TDependentEntity> : OwnedNavigationBuilder where TOwnerEntity : class where TDependentEntity : class { @@ -257,8 +260,8 @@ public virtual OwnershipBuilder WithOwner( /// The name of the reference navigation property on this entity type that represents the relationship. /// /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsOne( - string navigationName) + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>(string navigationName) where TNewDependentEntity : class => OwnsOneBuilder( new TypeIdentity(typeof(TNewDependentEntity), (Model)Metadata.DeclaringEntityType.Model), @@ -288,7 +291,8 @@ public virtual OwnedNavigationBuilder Own /// The name of the reference navigation property on this entity type that represents the relationship. /// /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsOne( + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( string ownedTypeName, string navigationName) where TNewDependentEntity : class @@ -320,8 +324,9 @@ public virtual OwnedNavigationBuilder Own /// the relationship (customer => customer.Address). /// /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsOne( - Expression> navigationExpression) + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( + Expression> navigationExpression) where TNewDependentEntity : class => OwnsOneBuilder( new TypeIdentity(typeof(TNewDependentEntity), (Model)Metadata.DeclaringEntityType.Model), @@ -352,7 +357,8 @@ public virtual OwnedNavigationBuilder Own /// the relationship (customer => customer.Address). /// /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsOne( + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( string ownedTypeName, Expression> navigationExpression) where TNewDependentEntity : class @@ -384,9 +390,10 @@ public virtual OwnedNavigationBuilder Own /// /// An action that performs configuration of the relationship. /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsOne( - string navigationName, - Action> buildAction) + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( + string navigationName, + Action> buildAction) where TNewDependentEntity : class { Check.NotEmpty(navigationName, nameof(navigationName)); @@ -456,7 +463,7 @@ public virtual OwnedNavigationBuilder OwnsOneAn object that can be used to configure the entity type. public new virtual OwnedNavigationBuilder OwnsOne( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) => (OwnedNavigationBuilder)base.OwnsOne(ownedTypeName, ownedType, navigationName, buildAction); @@ -486,7 +493,7 @@ public virtual OwnedNavigationBuilder OwnsOneAn action that performs configuration of the relationship. /// An object that can be used to configure the entity type. public new virtual OwnedNavigationBuilder OwnsOne( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) => (OwnedNavigationBuilder)base.OwnsOne(ownedType, navigationName, buildAction); @@ -516,10 +523,11 @@ public virtual OwnedNavigationBuilder OwnsOne /// An action that performs configuration of the relationship. /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsOne( - string ownedTypeName, - string navigationName, - Action> buildAction) + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( + string ownedTypeName, + string navigationName, + Action> buildAction) where TNewDependentEntity : class { Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)); @@ -557,9 +565,10 @@ public virtual OwnedNavigationBuilder OwnsOne /// An action that performs configuration of the relationship. /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsOne( - Expression> navigationExpression, - Action> buildAction) + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( + Expression> navigationExpression, + Action> buildAction) where TNewDependentEntity : class { Check.NotNull(navigationExpression, nameof(navigationExpression)); @@ -598,10 +607,11 @@ public virtual OwnedNavigationBuilder OwnsOne /// An action that performs configuration of the relationship. /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsOne( - string ownedTypeName, - Expression> navigationExpression, - Action> buildAction) + public virtual OwnedNavigationBuilder OwnsOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( + string ownedTypeName, + Expression> navigationExpression, + Action> buildAction) where TNewDependentEntity : class { Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)); @@ -615,7 +625,8 @@ public virtual OwnedNavigationBuilder OwnsOne OwnsOneBuilder( + private OwnedNavigationBuilder OwnsOneBuilder + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( TypeIdentity ownedType, MemberIdentity navigation) where TNewDependentEntity : class @@ -653,8 +664,8 @@ private OwnedNavigationBuilder OwnsOneBui /// The name of the reference navigation property on this entity type that represents the relationship. /// /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsMany( - string navigationName) + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>(string navigationName) where TNewDependentEntity : class => OwnsManyBuilder( new TypeIdentity(typeof(TNewDependentEntity), (Model)Metadata.DeclaringEntityType.Model), @@ -683,7 +694,8 @@ public virtual OwnedNavigationBuilder Own /// The name of the reference navigation property on this entity type that represents the relationship. /// /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsMany( + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( string ownedTypeName, string navigationName) where TNewDependentEntity : class @@ -714,7 +726,8 @@ public virtual OwnedNavigationBuilder Own /// the relationship (customer => customer.Address). /// /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsMany( + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( Expression?>> navigationExpression) where TNewDependentEntity : class => OwnsManyBuilder( @@ -745,7 +758,8 @@ public virtual OwnedNavigationBuilder Own /// the relationship (customer => customer.Address). /// /// An object that can be used to configure the owned type and the relationship. - public virtual OwnedNavigationBuilder OwnsMany( + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( string ownedTypeName, Expression?>> navigationExpression) where TNewDependentEntity : class @@ -776,7 +790,8 @@ public virtual OwnedNavigationBuilder Own /// /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsMany( + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( string navigationName, Action> buildAction) where TNewDependentEntity : class @@ -847,7 +862,7 @@ public virtual OwnedNavigationBuilder OwnsManyAn action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. public new virtual OwnedNavigationBuilder OwnsMany( - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) => (OwnedNavigationBuilder)base.OwnsMany(ownedType, navigationName, buildAction); @@ -878,7 +893,7 @@ public virtual OwnedNavigationBuilder OwnsManyAn object that can be used to configure the entity type. public new virtual OwnedNavigationBuilder OwnsMany( string ownedTypeName, - Type ownedType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ownedType, string navigationName, Action buildAction) => (OwnedNavigationBuilder)base.OwnsMany(ownedTypeName, ownedType, navigationName, buildAction); @@ -907,10 +922,11 @@ public virtual OwnedNavigationBuilder OwnsMany /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsMany( - string ownedTypeName, - string navigationName, - Action> buildAction) + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( + string ownedTypeName, + string navigationName, + Action> buildAction) where TNewDependentEntity : class { Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)); @@ -950,9 +966,10 @@ public virtual OwnedNavigationBuilder OwnsMany /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsMany( - Expression?>> navigationExpression, - Action> buildAction) + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( + Expression?>> navigationExpression, + Action> buildAction) where TNewDependentEntity : class { Check.NotNull(navigationExpression, nameof(navigationExpression)); @@ -993,10 +1010,11 @@ public virtual OwnedNavigationBuilder OwnsMany /// An action that performs configuration of the owned type and the relationship. /// An object that can be used to configure the entity type. - public virtual OwnedNavigationBuilder OwnsMany( - string ownedTypeName, - Expression?>> navigationExpression, - Action> buildAction) + public virtual OwnedNavigationBuilder OwnsMany + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewDependentEntity>( + string ownedTypeName, + Expression?>> navigationExpression, + Action> buildAction) where TNewDependentEntity : class { Check.NotEmpty(ownedTypeName, nameof(ownedTypeName)); @@ -1013,9 +1031,10 @@ public virtual OwnedNavigationBuilder OwnsMany OwnsManyBuilder( - TypeIdentity ownedType, - MemberIdentity navigation) + private OwnedNavigationBuilder OwnsManyBuilder + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewRelatedEntity>( + TypeIdentity ownedType, + MemberIdentity navigation) where TNewRelatedEntity : class { InternalForeignKeyBuilder relationship; @@ -1055,8 +1074,8 @@ private OwnedNavigationBuilder OwnsManyBuil /// end. /// /// An object that can be used to configure the relationship. - public virtual ReferenceNavigationBuilder HasOne( - string? navigationName) + public virtual ReferenceNavigationBuilder HasOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewRelatedEntity>(string? navigationName) where TNewRelatedEntity : class { var relatedEntityType = FindRelatedEntityType(typeof(TNewRelatedEntity), navigationName); @@ -1098,8 +1117,9 @@ public virtual ReferenceNavigationBuilder H /// configured without a navigation property on this end. /// /// An object that can be used to configure the relationship. - public virtual ReferenceNavigationBuilder HasOne( - Expression>? navigationExpression = null) + public virtual ReferenceNavigationBuilder HasOne + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TNewRelatedEntity>( + Expression>? navigationExpression = null) where TNewRelatedEntity : class { var navigation = navigationExpression?.GetMemberAccess(); diff --git a/src/EFCore/Metadata/Builders/PropertyBuilder.cs b/src/EFCore/Metadata/Builders/PropertyBuilder.cs index a3ec58aba26..8828ea44a61 100644 --- a/src/EFCore/Metadata/Builders/PropertyBuilder.cs +++ b/src/EFCore/Metadata/Builders/PropertyBuilder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Metadata.Builders; @@ -169,7 +170,8 @@ public virtual PropertyBuilder IsRowVersion() /// /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasValueGenerator() + public virtual PropertyBuilder HasValueGenerator + <[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TGenerator>() where TGenerator : ValueGenerator { Builder.HasValueGenerator(typeof(TGenerator), ConfigurationSource.Explicit); @@ -202,7 +204,8 @@ public virtual PropertyBuilder HasValueGenerator() /// /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasValueGenerator(Type? valueGeneratorType) + public virtual PropertyBuilder HasValueGenerator( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? valueGeneratorType) { Builder.HasValueGenerator(valueGeneratorType, ConfigurationSource.Explicit); @@ -266,7 +269,8 @@ public virtual PropertyBuilder HasValueGenerator(Func /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasValueGeneratorFactory() + public virtual PropertyBuilder HasValueGeneratorFactory + <[DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] TFactory>() where TFactory : ValueGeneratorFactory => HasValueGeneratorFactory(typeof(TFactory)); @@ -296,7 +300,8 @@ public virtual PropertyBuilder HasValueGeneratorFactory() /// /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasValueGeneratorFactory(Type? valueGeneratorFactoryType) + public virtual PropertyBuilder HasValueGeneratorFactory( + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? valueGeneratorFactoryType) { Builder.HasValueGeneratorFactory(valueGeneratorFactoryType, ConfigurationSource.Explicit); @@ -441,7 +446,7 @@ public virtual PropertyBuilder UsePropertyAccessMode(PropertyAccessMode property /// /// The type to convert to and from or a type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasConversion() + public virtual PropertyBuilder HasConversion<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TConversion>() => HasConversion(typeof(TConversion)); /// @@ -450,7 +455,8 @@ public virtual PropertyBuilder HasConversion() /// /// The type to convert to and from or a type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasConversion(Type? conversionType) + public virtual PropertyBuilder HasConversion( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? conversionType) { if (typeof(ValueConverter).IsAssignableFrom(conversionType)) { @@ -480,7 +486,9 @@ public virtual PropertyBuilder HasConversion(ValueConverter? converter) /// The comparer to use for values before conversion. /// The type to convert to and from or a type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasConversion(ValueComparer? valueComparer) + public virtual PropertyBuilder HasConversion< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TConversion>( + ValueComparer? valueComparer) => HasConversion(typeof(TConversion), valueComparer); /// @@ -491,7 +499,10 @@ public virtual PropertyBuilder HasConversion(ValueComparer? valueCo /// The comparer to use for the provider values. /// The type to convert to and from or a type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasConversion(ValueComparer? valueComparer, ValueComparer? providerComparer) + public virtual PropertyBuilder HasConversion + <[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TConversion>( + ValueComparer? valueComparer, + ValueComparer? providerComparer) => HasConversion(typeof(TConversion), valueComparer, providerComparer); /// @@ -501,9 +512,12 @@ public virtual PropertyBuilder HasConversion(ValueComparer? valueCo /// The type to convert to and from or a type that inherits from . /// The comparer to use for values before conversion. /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasConversion(Type conversionType, ValueComparer? valueComparer) + public virtual PropertyBuilder HasConversion( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type conversionType, + ValueComparer? valueComparer) => HasConversion(conversionType, valueComparer, null); + // DynamicallyAccessedMemberTypes.PublicParameterlessConstructor /// /// Configures the property so that the property value is converted before /// writing to the database and converted back when reading from the database. @@ -512,7 +526,10 @@ public virtual PropertyBuilder HasConversion(Type conversionType, ValueComparer? /// The comparer to use for values before conversion. /// The comparer to use for the provider values. /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasConversion(Type conversionType, ValueComparer? valueComparer, ValueComparer? providerComparer) + public virtual PropertyBuilder HasConversion( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type conversionType, + ValueComparer? valueComparer, + ValueComparer? providerComparer) { Check.NotNull(conversionType, nameof(conversionType)); @@ -565,7 +582,9 @@ public virtual PropertyBuilder HasConversion(ValueConverter? converter, ValueCom /// The type to convert to and from or a type that inherits from . /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasConversion() + public virtual PropertyBuilder HasConversion< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TConversion, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TComparer>() where TComparer : ValueComparer => HasConversion(typeof(TConversion), typeof(TComparer)); @@ -577,7 +596,10 @@ public virtual PropertyBuilder HasConversion() /// A type that inherits from . /// A type that inherits from to use for the provider values. /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasConversion() + public virtual PropertyBuilder HasConversion< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TConversion, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TComparer, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TProviderComparer>() where TComparer : ValueComparer where TProviderComparer : ValueComparer => HasConversion(typeof(TConversion), typeof(TComparer), typeof(TProviderComparer)); @@ -589,7 +611,9 @@ public virtual PropertyBuilder HasConversionThe type to convert to and from or a type that inherits from . /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasConversion(Type conversionType, Type? comparerType) + public virtual PropertyBuilder HasConversion( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type conversionType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType) => HasConversion(conversionType, comparerType, null); /// @@ -600,7 +624,10 @@ public virtual PropertyBuilder HasConversion(Type conversionType, Type? comparer /// A type that inherits from . /// A type that inherits from to use for the provider values. /// The same builder instance so that multiple configuration calls can be chained. - public virtual PropertyBuilder HasConversion(Type conversionType, Type? comparerType, Type? providerComparerType) + public virtual PropertyBuilder HasConversion( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type conversionType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? providerComparerType) { Check.NotNull(conversionType, nameof(conversionType)); diff --git a/src/EFCore/Metadata/Builders/PropertyBuilder`.cs b/src/EFCore/Metadata/Builders/PropertyBuilder`.cs index 44485ab0741..5412788ac21 100644 --- a/src/EFCore/Metadata/Builders/PropertyBuilder`.cs +++ b/src/EFCore/Metadata/Builders/PropertyBuilder`.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// @@ -118,7 +120,8 @@ public PropertyBuilder(IMutableProperty property) /// /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasValueGenerator() + public new virtual PropertyBuilder HasValueGenerator + <[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TGenerator>() where TGenerator : ValueGenerator => (PropertyBuilder)base.HasValueGenerator(); @@ -147,7 +150,8 @@ public PropertyBuilder(IMutableProperty property) /// /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasValueGenerator(Type? valueGeneratorType) + public new virtual PropertyBuilder HasValueGenerator( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? valueGeneratorType) => (PropertyBuilder)base.HasValueGenerator(valueGeneratorType); /// @@ -201,7 +205,8 @@ public PropertyBuilder(IMutableProperty property) /// /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasValueGeneratorFactory() + public new virtual PropertyBuilder HasValueGeneratorFactory + <[DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] TFactory>() where TFactory : ValueGeneratorFactory => (PropertyBuilder)base.HasValueGeneratorFactory(); @@ -231,7 +236,8 @@ public PropertyBuilder(IMutableProperty property) /// /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasValueGeneratorFactory(Type? valueGeneratorFactoryType) + public new virtual PropertyBuilder HasValueGeneratorFactory( + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? valueGeneratorFactoryType) => (PropertyBuilder)base.HasValueGeneratorFactory(valueGeneratorFactoryType); /// @@ -339,7 +345,8 @@ public PropertyBuilder(IMutableProperty property) /// /// The type to convert to and from or a type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasConversion() + public new virtual PropertyBuilder HasConversion + <[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TConversion>() => (PropertyBuilder)base.HasConversion(); /// @@ -348,7 +355,8 @@ public PropertyBuilder(IMutableProperty property) /// /// The type to convert to and from or a type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasConversion(Type? providerClrType) + public new virtual PropertyBuilder HasConversion( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? providerClrType) => (PropertyBuilder)base.HasConversion(providerClrType); /// @@ -393,7 +401,9 @@ public virtual PropertyBuilder HasConversion(ValueConverte /// The type to convert to and from or a type that inherits from . /// The comparer to use for values before conversion. /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasConversion(ValueComparer? valueComparer) + public new virtual PropertyBuilder HasConversion + <[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TConversion>( + ValueComparer? valueComparer) => (PropertyBuilder)base.HasConversion(valueComparer); /// @@ -404,7 +414,10 @@ public virtual PropertyBuilder HasConversion(ValueConverte /// The comparer to use for values before conversion. /// The comparer to use for the provider values. /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasConversion(ValueComparer? valueComparer, ValueComparer? providerComparer) + public new virtual PropertyBuilder HasConversion + <[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TConversion>( + ValueComparer? valueComparer, + ValueComparer? providerComparer) => (PropertyBuilder)base.HasConversion(valueComparer, providerComparer); /// @@ -415,7 +428,7 @@ public virtual PropertyBuilder HasConversion(ValueConverte /// The comparer to use for values before conversion. /// The same builder instance so that multiple configuration calls can be chained. public new virtual PropertyBuilder HasConversion( - Type conversionType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type conversionType, ValueComparer? valueComparer) => (PropertyBuilder)base.HasConversion(conversionType, valueComparer); @@ -428,7 +441,7 @@ public virtual PropertyBuilder HasConversion(ValueConverte /// The comparer to use for the provider values. /// The same builder instance so that multiple configuration calls can be chained. public new virtual PropertyBuilder HasConversion( - Type conversionType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type conversionType, ValueComparer? valueComparer, ValueComparer? providerComparer) => (PropertyBuilder)base.HasConversion(conversionType, valueComparer, providerComparer); @@ -535,7 +548,9 @@ public virtual PropertyBuilder HasConversion( /// The type to convert to and from or a type that inherits from . /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasConversion() + public new virtual PropertyBuilder HasConversion< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TConversion, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TComparer>() where TComparer : ValueComparer => (PropertyBuilder)base.HasConversion(); @@ -547,7 +562,10 @@ public virtual PropertyBuilder HasConversion( /// A type that inherits from . /// A type that inherits from to use for the provider values. /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasConversion() + public new virtual PropertyBuilder HasConversion< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TConversion, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TComparer, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TProviderComparer>() where TComparer : ValueComparer where TProviderComparer : ValueComparer => (PropertyBuilder)base.HasConversion(); @@ -559,7 +577,9 @@ public virtual PropertyBuilder HasConversion( /// The type to convert to and from or a type that inherits from . /// A type that inherits from . /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasConversion(Type conversionType, Type? comparerType) + public new virtual PropertyBuilder HasConversion( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type conversionType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType) => (PropertyBuilder)base.HasConversion(conversionType, comparerType); /// @@ -570,6 +590,9 @@ public virtual PropertyBuilder HasConversion( /// A type that inherits from . /// A type that inherits from to use for the provider values. /// The same builder instance so that multiple configuration calls can be chained. - public new virtual PropertyBuilder HasConversion(Type conversionType, Type? comparerType, Type? providerComparerType) + public new virtual PropertyBuilder HasConversion( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type conversionType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? providerComparerType) => (PropertyBuilder)base.HasConversion(conversionType, comparerType, providerComparerType); } diff --git a/src/EFCore/Metadata/IConventionEntityType.cs b/src/EFCore/Metadata/IConventionEntityType.cs index d3cfec7c60f..1867405f0f0 100644 --- a/src/EFCore/Metadata/IConventionEntityType.cs +++ b/src/EFCore/Metadata/IConventionEntityType.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Metadata; @@ -784,6 +785,7 @@ public interface IConventionEntityType : IReadOnlyEntityType, IConventionTypeBas /// The corresponding member on the entity class. /// Indicates whether the configuration was specified using a data annotation. /// The newly created property. + [RequiresUnreferencedCode("Currently used only in tests")] IConventionProperty? AddProperty(MemberInfo memberInfo, bool fromDataAnnotation = false) => AddProperty( memberInfo.GetSimpleMemberName(), memberInfo.GetMemberType(), @@ -807,7 +809,7 @@ public interface IConventionEntityType : IReadOnlyEntityType, IConventionTypeBas /// The newly created property. IConventionProperty? AddProperty( string name, - Type propertyType, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, bool setTypeConfigurationSource = true, bool fromDataAnnotation = false); @@ -829,7 +831,7 @@ public interface IConventionEntityType : IReadOnlyEntityType, IConventionTypeBas /// The newly created property. IConventionProperty? AddProperty( string name, - Type propertyType, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, MemberInfo? memberInfo, bool setTypeConfigurationSource = true, bool fromDataAnnotation = false); @@ -844,7 +846,7 @@ public interface IConventionEntityType : IReadOnlyEntityType, IConventionTypeBas /// The newly created property. IConventionProperty? AddIndexerProperty( string name, - Type propertyType, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, bool setTypeConfigurationSource = true, bool fromDataAnnotation = false) { diff --git a/src/EFCore/Metadata/IConventionModel.cs b/src/EFCore/Metadata/IConventionModel.cs index 616ec23580e..f30bdd8510f 100644 --- a/src/EFCore/Metadata/IConventionModel.cs +++ b/src/EFCore/Metadata/IConventionModel.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata; /// @@ -18,6 +20,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata; /// See Model building conventions for more information and examples. /// /// +[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072", Justification = "TODO")] public interface IConventionModel : IReadOnlyModel, IConventionAnnotatable { /// @@ -88,7 +91,9 @@ public interface IConventionModel : IReadOnlyModel, IConventionAnnotatable /// The CLR class that is used to represent instances of the entity type. /// Indicates whether the configuration was specified using a data annotation. /// The new entity type. - IConventionEntityType? AddEntityType(Type type, bool fromDataAnnotation = false); + IConventionEntityType? AddEntityType( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation = false); /// /// Adds a shared type entity type to the model. @@ -101,7 +106,10 @@ public interface IConventionModel : IReadOnlyModel, IConventionAnnotatable /// The CLR class that is used to represent instances of the entity type. /// Indicates whether the configuration was specified using a data annotation. /// The new entity type. - IConventionEntityType? AddEntityType(string name, Type clrType, bool fromDataAnnotation = false); + IConventionEntityType? AddEntityType( + string name, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type clrType, + bool fromDataAnnotation = false); /// /// Adds an owned entity type with a defining navigation to the model. @@ -126,7 +134,7 @@ public interface IConventionModel : IReadOnlyModel, IConventionAnnotatable /// Indicates whether the configuration was specified using a data annotation. /// The new entity type. IConventionEntityType? AddEntityType( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, string definingNavigationName, IConventionEntityType definingEntityType, bool fromDataAnnotation = false); @@ -149,7 +157,9 @@ public interface IConventionModel : IReadOnlyModel, IConventionAnnotatable /// The CLR class that is used to represent instances of the entity type. /// Indicates whether the configuration was specified using a data annotation. /// The new entity type. - IConventionEntityType? AddOwnedEntityType(Type type, bool fromDataAnnotation = false); + IConventionEntityType? AddOwnedEntityType( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation = false); /// /// Adds an owned shared type entity type to the model. @@ -162,7 +172,10 @@ public interface IConventionModel : IReadOnlyModel, IConventionAnnotatable /// The CLR class that is used to represent instances of the entity type. /// Indicates whether the configuration was specified using a data annotation. /// The new entity type. - IConventionEntityType? AddOwnedEntityType(string name, Type clrType, bool fromDataAnnotation = false); + IConventionEntityType? AddOwnedEntityType( + string name, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type clrType, + bool fromDataAnnotation = false); /// /// Gets the entity with the given name. Returns if no entity type with the given name is found @@ -332,7 +345,7 @@ public interface IConventionModel : IReadOnlyModel, IConventionAnnotatable /// if the given type is marked as owned, /// otherwise. /// - bool IsOwned(Type type) + bool IsOwned([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type) => FindIsOwnedConfigurationSource(type) != null; /// @@ -388,7 +401,7 @@ bool IsOwned(Type type) /// /// The entity type that might be ignored. /// if the given entity type is ignored. - bool IsIgnoredType(Type type); + bool IsIgnoredType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type); /// /// Indicates whether the given entity type name is ignored. diff --git a/src/EFCore/Metadata/IConventionProperty.cs b/src/EFCore/Metadata/IConventionProperty.cs index 90e00d0c2b7..72358454f63 100644 --- a/src/EFCore/Metadata/IConventionProperty.cs +++ b/src/EFCore/Metadata/IConventionProperty.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata; /// @@ -317,7 +319,7 @@ bool IsImplicitlyCreated() /// Indicates whether the configuration was specified using a data annotation. /// The configured value. Type? SetValueGeneratorFactory( - Type? valueGeneratorFactory, + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? valueGeneratorFactory, bool fromDataAnnotation = false); /// @@ -342,7 +344,9 @@ bool IsImplicitlyCreated() /// /// Indicates whether the configuration was specified using a data annotation. /// The configured value. - Type? SetValueConverter(Type? converterType, bool fromDataAnnotation = false); + Type? SetValueConverter( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType, + bool fromDataAnnotation = false); /// /// Returns the configuration source for . @@ -380,7 +384,10 @@ bool IsImplicitlyCreated() /// /// Indicates whether the configuration was specified using a data annotation. /// The configured value. - Type? SetValueComparer(Type? comparerType, bool fromDataAnnotation = false); + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type? SetValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation = false); /// /// Returns the configuration source for . @@ -404,7 +411,10 @@ bool IsImplicitlyCreated() /// /// Indicates whether the configuration was specified using a data annotation. /// The configured value. - Type? SetProviderValueComparer(Type? comparerType, bool fromDataAnnotation = false); + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type? SetProviderValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation = false); /// /// Returns the configuration source for . diff --git a/src/EFCore/Metadata/IEntityType.cs b/src/EFCore/Metadata/IEntityType.cs index c912d966a0a..31ec35acb13 100644 --- a/src/EFCore/Metadata/IEntityType.cs +++ b/src/EFCore/Metadata/IEntityType.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata; /// @@ -576,4 +578,13 @@ public interface IEntityType : IReadOnlyEntityType, ITypeBase /// Returns the declared triggers on the entity type. /// new IEnumerable GetDeclaredTriggers(); + + internal const DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes = + System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicProperties + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicFields + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces; } diff --git a/src/EFCore/Metadata/IModel.cs b/src/EFCore/Metadata/IModel.cs index 833ead79edc..55e5c5b224e 100644 --- a/src/EFCore/Metadata/IModel.cs +++ b/src/EFCore/Metadata/IModel.cs @@ -126,7 +126,7 @@ RuntimeModelDependencies GetModelDependencies() /// /// The type to find the corresponding entity type for. /// The entity type, or if none is found. - new IEntityType? FindEntityType(Type type); + new IEntityType? FindEntityType([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type); /// /// Gets the entity type for the given name, defining navigation name diff --git a/src/EFCore/Metadata/IMutableEntityType.cs b/src/EFCore/Metadata/IMutableEntityType.cs index 5798de4c7b3..65a54085369 100644 --- a/src/EFCore/Metadata/IMutableEntityType.cs +++ b/src/EFCore/Metadata/IMutableEntityType.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Metadata; @@ -677,7 +678,10 @@ IMutableIndex AddIndex(IMutableProperty property, string name) /// /// /// The newly created property. - IMutableProperty AddProperty(string name, Type propertyType, MemberInfo? memberInfo); + IMutableProperty AddProperty( + string name, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, + MemberInfo? memberInfo); /// /// Gets a property on the given entity type. Returns if no property is found. @@ -740,6 +744,7 @@ IMutableIndex AddIndex(IMutableProperty property, string name) /// /// The corresponding member on the entity class. /// The newly created property. + [RequiresUnreferencedCode("Currently used only in tests")] IMutableProperty AddProperty(MemberInfo memberInfo) => AddProperty(memberInfo.GetSimpleMemberName(), memberInfo.GetMemberType(), memberInfo); @@ -756,7 +761,7 @@ IMutableProperty AddProperty(MemberInfo memberInfo) /// The name of the property to add. /// The type of value the property will hold. /// The newly created property. - IMutableProperty AddProperty(string name, Type propertyType); + IMutableProperty AddProperty(string name, [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType); /// /// Adds a property backed up by an indexer to this entity type. @@ -766,7 +771,7 @@ IMutableProperty AddProperty(MemberInfo memberInfo) /// The newly created property. IMutableProperty AddIndexerProperty( string name, - Type propertyType) + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType) { var indexerPropertyInfo = FindIndexerPropertyInfo(); if (indexerPropertyInfo == null) diff --git a/src/EFCore/Metadata/IMutableModel.cs b/src/EFCore/Metadata/IMutableModel.cs index 23f11a3fc0b..6ef2ee0fd02 100644 --- a/src/EFCore/Metadata/IMutableModel.cs +++ b/src/EFCore/Metadata/IMutableModel.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata; /// @@ -66,7 +68,7 @@ public interface IMutableModel : IReadOnlyModel, IMutableAnnotatable /// /// The CLR class that is used to represent instances of the entity type. /// The new entity type. - IMutableEntityType AddEntityType(Type type); + IMutableEntityType AddEntityType([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type); /// /// Adds a shared type entity type to the model. @@ -78,7 +80,7 @@ public interface IMutableModel : IReadOnlyModel, IMutableAnnotatable /// The name of the entity to be added. /// The CLR class that is used to represent instances of the entity type. /// The new entity type. - IMutableEntityType AddEntityType(string name, Type type); + IMutableEntityType AddEntityType(string name, [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type); /// /// Adds an owned entity type with a defining navigation to the model. @@ -100,7 +102,7 @@ IMutableEntityType AddEntityType( /// The defining entity type. /// The new entity type. IMutableEntityType AddEntityType( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, string definingNavigationName, IMutableEntityType definingEntityType); @@ -120,7 +122,7 @@ IMutableEntityType AddEntityType( /// /// The CLR class that is used to represent instances of the entity type. /// The new entity type. - IMutableEntityType AddOwnedEntityType(Type type); + IMutableEntityType AddOwnedEntityType([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type); /// /// Adds an owned shared type entity type to the model. @@ -132,7 +134,7 @@ IMutableEntityType AddEntityType( /// The name of the entity to be added. /// The CLR class that is used to represent instances of the entity type. /// The new entity type. - IMutableEntityType AddOwnedEntityType(string name, Type type); + IMutableEntityType AddOwnedEntityType(string name, [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type); /// /// Gets the entity with the given name. Returns if no entity type with the given name is found @@ -292,7 +294,7 @@ IMutableEntityType AddEntityType( /// if a matching entity type should be configured as owned when discovered, /// otherwise. /// - bool IsOwned(Type type); + bool IsOwned([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type); /// /// Marks the given entity type name as ignored, preventing conventions from adding a matching entity type to the model. diff --git a/src/EFCore/Metadata/IMutableProperty.cs b/src/EFCore/Metadata/IMutableProperty.cs index a253dcf74c7..d816bb6b5cc 100644 --- a/src/EFCore/Metadata/IMutableProperty.cs +++ b/src/EFCore/Metadata/IMutableProperty.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata; /// @@ -194,7 +196,8 @@ public interface IMutableProperty : IReadOnlyProperty, IMutablePropertyBase /// A factory that will be used to create the value generator, or to /// clear any previously set factory. /// - void SetValueGeneratorFactory(Type? valueGeneratorFactory); + void SetValueGeneratorFactory( + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? valueGeneratorFactory); /// /// Sets the custom for this property. @@ -208,7 +211,7 @@ public interface IMutableProperty : IReadOnlyProperty, IMutablePropertyBase /// /// A type that derives from , or to remove any previously set converter. /// - void SetValueConverter(Type? converterType); + void SetValueConverter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType); /// /// Sets the type that the property value will be converted to before being sent to the database provider. @@ -234,7 +237,7 @@ public interface IMutableProperty : IReadOnlyProperty, IMutablePropertyBase /// /// A type that derives from , or to remove any previously set comparer. /// - void SetValueComparer(Type? comparerType); + void SetValueComparer([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType); /// /// Sets the custom to use for the provider values for this property. @@ -248,5 +251,5 @@ public interface IMutableProperty : IReadOnlyProperty, IMutablePropertyBase /// /// A type that derives from , or to remove any previously set comparer. /// - void SetProviderValueComparer(Type? comparerType); + void SetProviderValueComparer([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType); } diff --git a/src/EFCore/Metadata/IProperty.cs b/src/EFCore/Metadata/IProperty.cs index 212e3135853..40ee5b4c195 100644 --- a/src/EFCore/Metadata/IProperty.cs +++ b/src/EFCore/Metadata/IProperty.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; namespace Microsoft.EntityFrameworkCore.Metadata; @@ -96,4 +97,13 @@ IEqualityComparer CreateKeyEqualityComparer() /// /// The comparer. new ValueComparer GetProviderValueComparer(); + + internal const DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes = + System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicProperties + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicFields + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces; } diff --git a/src/EFCore/Metadata/IReadOnlyModel.cs b/src/EFCore/Metadata/IReadOnlyModel.cs index e33e989e0c6..2621039a6f2 100644 --- a/src/EFCore/Metadata/IReadOnlyModel.cs +++ b/src/EFCore/Metadata/IReadOnlyModel.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Text; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -61,7 +62,7 @@ public interface IReadOnlyModel : IReadOnlyAnnotatable /// /// The CLR type. /// Whether the CLR type is used by shared type entities in the model. - bool IsShared(Type type); + bool IsShared([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type); /// /// Gets all entity types defined in the model. diff --git a/src/EFCore/Metadata/IReadOnlyPropertyBase.cs b/src/EFCore/Metadata/IReadOnlyPropertyBase.cs index e9bab518dfd..ce49c16bd77 100644 --- a/src/EFCore/Metadata/IReadOnlyPropertyBase.cs +++ b/src/EFCore/Metadata/IReadOnlyPropertyBase.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata; /// @@ -24,6 +26,7 @@ public interface IReadOnlyPropertyBase : IReadOnlyAnnotatable /// /// Gets the type of value that this property-like object holds. /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes | IProperty.DynamicallyAccessedMemberTypes)] Type ClrType { get; } /// diff --git a/src/EFCore/Metadata/IReadOnlyTypeBase.cs b/src/EFCore/Metadata/IReadOnlyTypeBase.cs index f60e522cfad..c7a621e54fd 100644 --- a/src/EFCore/Metadata/IReadOnlyTypeBase.cs +++ b/src/EFCore/Metadata/IReadOnlyTypeBase.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; +using Microsoft.EntityFrameworkCore.Metadata.Internal; + namespace Microsoft.EntityFrameworkCore.Metadata; /// @@ -29,6 +32,7 @@ public interface IReadOnlyTypeBase : IReadOnlyAnnotatable /// Shadow types are not currently supported in a model that is used at runtime with a . /// Therefore, shadow types will only exist in migration model snapshots, etc. /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type ClrType { get; } /// diff --git a/src/EFCore/Metadata/Internal/CollectionTypeFactory.cs b/src/EFCore/Metadata/Internal/CollectionTypeFactory.cs index 8146ba42eef..20fd3e7b22f 100644 --- a/src/EFCore/Metadata/Internal/CollectionTypeFactory.cs +++ b/src/EFCore/Metadata/Internal/CollectionTypeFactory.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -21,6 +22,10 @@ public class CollectionTypeFactory /// public virtual Type? TryFindTypeToInstantiate( Type entityType, + [DynamicallyAccessedMembers( + DynamicallyAccessedMemberTypes.PublicConstructors | + DynamicallyAccessedMemberTypes.NonPublicConstructors | + DynamicallyAccessedMemberTypes.Interfaces)] Type collectionType, bool requireFullNotifications) { diff --git a/src/EFCore/Metadata/Internal/EntityType.cs b/src/EFCore/Metadata/Internal/EntityType.cs index 90b71708008..213e1088828 100644 --- a/src/EFCore/Metadata/Internal/EntityType.cs +++ b/src/EFCore/Metadata/Internal/EntityType.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Internal; @@ -94,7 +95,11 @@ public EntityType(string name, Model model, bool owned, ConfigurationSource conf /// 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 EntityType(Type type, Model model, bool owned, ConfigurationSource configurationSource) + public EntityType( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + Model model, + bool owned, + ConfigurationSource configurationSource) : base(type, model, configurationSource) { if (!type.IsValidEntityType()) @@ -120,7 +125,12 @@ public EntityType(Type type, Model model, bool owned, ConfigurationSource config /// 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 EntityType(string name, Type type, Model model, bool owned, ConfigurationSource configurationSource) + public EntityType( + string name, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + Model model, + bool owned, + ConfigurationSource configurationSource) : base(name, type, model, configurationSource) { if (!type.IsValidEntityType()) @@ -2304,7 +2314,7 @@ public virtual IEnumerable GetIndexes() /// public virtual Property? AddProperty( string name, - Type propertyType, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, ConfigurationSource? typeConfigurationSource, ConfigurationSource configurationSource) { @@ -2325,6 +2335,7 @@ public virtual IEnumerable GetIndexes() /// 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. /// + [RequiresUnreferencedCode("Use an overload that accepts a type")] public virtual Property? AddProperty( MemberInfo memberInfo, ConfigurationSource configurationSource) @@ -2341,6 +2352,7 @@ public virtual IEnumerable GetIndexes() /// 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. /// + [RequiresUnreferencedCode("Use an overload that accepts a type")] public virtual Property? AddProperty( string name, ConfigurationSource configurationSource) @@ -2370,7 +2382,7 @@ public virtual IEnumerable GetIndexes() /// public virtual Property? AddProperty( string name, - Type propertyType, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, MemberInfo? memberInfo, ConfigurationSource? typeConfigurationSource, ConfigurationSource configurationSource) @@ -4859,7 +4871,9 @@ IMutableProperty IMutableEntityType.AddProperty(string name) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IMutableProperty IMutableEntityType.AddProperty(string name, Type propertyType) + IMutableProperty IMutableEntityType.AddProperty( + string name, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType) => AddProperty( name, propertyType, @@ -4875,7 +4889,7 @@ IMutableProperty IMutableEntityType.AddProperty(string name, Type propertyType) [DebuggerStepThrough] IConventionProperty? IConventionEntityType.AddProperty( string name, - Type propertyType, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, bool setTypeConfigurationSource, bool fromDataAnnotation) => AddProperty( @@ -4893,7 +4907,10 @@ IMutableProperty IMutableEntityType.AddProperty(string name, Type propertyType) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IMutableProperty IMutableEntityType.AddProperty(string name, Type propertyType, MemberInfo? memberInfo) + IMutableProperty IMutableEntityType.AddProperty( + string name, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, + MemberInfo? memberInfo) => AddProperty( name, propertyType, memberInfo, ConfigurationSource.Explicit, ConfigurationSource.Explicit)!; @@ -4907,7 +4924,7 @@ IMutableProperty IMutableEntityType.AddProperty(string name, Type propertyType, [DebuggerStepThrough] IConventionProperty? IConventionEntityType.AddProperty( string name, - Type propertyType, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type propertyType, MemberInfo? memberInfo, bool setTypeConfigurationSource, bool fromDataAnnotation) diff --git a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs index 3f74eb23be1..cf58729b9d0 100644 --- a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Globalization; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal; @@ -484,7 +485,7 @@ public virtual bool CanRemoveKey(ConfigurationSource configurationSource) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalPropertyBuilder? Property( - Type? propertyType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type? propertyType, string propertyName, ConfigurationSource? typeConfigurationSource, ConfigurationSource? configurationSource) @@ -518,7 +519,7 @@ public virtual bool CanRemoveKey(ConfigurationSource configurationSource) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalPropertyBuilder? IndexerProperty( - Type? propertyType, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type? propertyType, string propertyName, ConfigurationSource? configurationSource) { @@ -533,7 +534,7 @@ public virtual bool CanRemoveKey(ConfigurationSource configurationSource) } private InternalPropertyBuilder? Property( - Type? propertyType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type? propertyType, string propertyName, MemberInfo? memberInfo, ConfigurationSource? typeConfigurationSource, @@ -706,7 +707,7 @@ public virtual bool CanRemoveKey(ConfigurationSource configurationSource) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool CanHaveProperty( - Type? propertyType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type? propertyType, string propertyName, MemberInfo? memberInfo, ConfigurationSource? typeConfigurationSource, @@ -727,7 +728,7 @@ public virtual bool CanHaveProperty( } private bool CanAddProperty( - Type? propertyType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type? propertyType, string propertyName, ConfigurationSource configurationSource, bool checkClrProperty = false) @@ -1065,7 +1066,10 @@ private bool CanAddServiceProperty(MemberInfo memberInfo, ConfigurationSource co /// 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 CanHaveNavigation(string navigationName, Type? type, ConfigurationSource? configurationSource) + public virtual bool CanHaveNavigation( + string navigationName, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type? type, + ConfigurationSource? configurationSource) { var existingNavigation = Metadata.FindNavigation(navigationName); return existingNavigation != null @@ -1082,7 +1086,10 @@ public virtual bool CanHaveNavigation(string navigationName, Type? type, Configu /// 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 CanAddNavigation(string navigationName, Type? type, ConfigurationSource configurationSource) + public virtual bool CanAddNavigation( + string navigationName, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type? type, + ConfigurationSource configurationSource) => !IsIgnored(navigationName, configurationSource) && (type == null || CanBeNavigation(type, configurationSource)) && Metadata.FindPropertiesInHierarchy(navigationName).Cast() @@ -1115,7 +1122,10 @@ public virtual bool CanHaveSkipNavigation(string skipNavigationName, Type? type, && CanAddSkipNavigation(skipNavigationName, type, configurationSource.Value); } - private bool CanAddSkipNavigation(string skipNavigationName, Type? type, ConfigurationSource configurationSource) + private bool CanAddSkipNavigation( + string skipNavigationName, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type? type, + ConfigurationSource configurationSource) => !IsIgnored(skipNavigationName, configurationSource) && (type == null || CanBeNavigation(type, configurationSource)) && Metadata.FindPropertiesInHierarchy(skipNavigationName).Cast() @@ -3727,7 +3737,7 @@ private static bool Contains(IReadOnlyForeignKey? inheritedFk, IReadOnlyForeignK /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalEntityTypeBuilder? GetTargetEntityTypeBuilder( - Type targetClrType, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type targetClrType, MemberInfo navigationInfo, ConfigurationSource? configurationSource, bool? targetShouldBeOwned = null) @@ -5892,7 +5902,10 @@ bool IConventionEntityTypeBuilder.CanRemoveRelationship(IConventionForeignKey fo /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - bool IConventionEntityTypeBuilder.CanHaveNavigation(string navigationName, Type? type, bool fromDataAnnotation) + bool IConventionEntityTypeBuilder.CanHaveNavigation( + string navigationName, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type? type, + bool fromDataAnnotation) => CanHaveNavigation( navigationName, type, diff --git a/src/EFCore/Metadata/Internal/InternalModelBuilder.cs b/src/EFCore/Metadata/Internal/InternalModelBuilder.cs index f2fa398780a..472b3554d51 100644 --- a/src/EFCore/Metadata/Internal/InternalModelBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalModelBuilder.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata.Internal; /// @@ -51,7 +53,7 @@ public override InternalModelBuilder ModelBuilder /// public virtual InternalEntityTypeBuilder? SharedTypeEntity( string name, - Type? type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type? type, ConfigurationSource configurationSource, bool? shouldBeOwned = false) => Entity(new TypeIdentity(name, type ?? Model.DefaultPropertyBagType), configurationSource, shouldBeOwned); @@ -63,7 +65,7 @@ public override InternalModelBuilder ModelBuilder /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalEntityTypeBuilder? Entity( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, ConfigurationSource configurationSource, bool? shouldBeOwned = null) => Entity(new TypeIdentity(type, Metadata), configurationSource, shouldBeOwned); @@ -267,7 +269,7 @@ public override InternalModelBuilder ModelBuilder /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalEntityTypeBuilder? Entity( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, string definingNavigationName, EntityType definingEntityType, ConfigurationSource configurationSource) @@ -306,7 +308,7 @@ public override InternalModelBuilder ModelBuilder /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual IConventionOwnedEntityTypeBuilder? Owned( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, ConfigurationSource configurationSource) { if (IsIgnored(type, configurationSource) @@ -361,7 +363,9 @@ private bool IsOwned(in TypeIdentity type) /// 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 IsIgnored(Type type, ConfigurationSource? configurationSource) + public virtual bool IsIgnored( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + ConfigurationSource? configurationSource) => IsIgnored(new TypeIdentity(type, Metadata), configurationSource); /// @@ -397,7 +401,10 @@ private bool IsIgnored(in TypeIdentity type, ConfigurationSource? configurationS /// 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 CanBeConfigured(Type type, TypeConfigurationType configurationType, ConfigurationSource configurationSource) + public virtual bool CanBeConfigured( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type, + TypeConfigurationType configurationType, + ConfigurationSource configurationSource) { if (configurationSource == ConfigurationSource.Explicit) { @@ -423,7 +430,9 @@ public virtual bool CanBeConfigured(Type type, TypeConfigurationType configurati /// 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 InternalModelBuilder? Ignore(Type type, ConfigurationSource configurationSource) + public virtual InternalModelBuilder? Ignore( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + ConfigurationSource configurationSource) => Ignore(new TypeIdentity(type, Metadata), configurationSource); /// @@ -487,7 +496,9 @@ public virtual bool CanBeConfigured(Type type, TypeConfigurationType configurati /// 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 CanIgnore(Type type, ConfigurationSource configurationSource) + public virtual bool CanIgnore( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + ConfigurationSource configurationSource) => CanIgnore(new TypeIdentity(type, Metadata), configurationSource); /// @@ -683,7 +694,7 @@ IConventionModel IConventionModelBuilder.Metadata [DebuggerStepThrough] IConventionEntityTypeBuilder? IConventionModelBuilder.SharedTypeEntity( string name, - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, bool? shouldBeOwned, bool fromDataAnnotation) => SharedTypeEntity( @@ -696,7 +707,10 @@ IConventionModel IConventionModelBuilder.Metadata /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IConventionEntityTypeBuilder? IConventionModelBuilder.Entity(Type type, bool? shouldBeOwned, bool fromDataAnnotation) + IConventionEntityTypeBuilder? IConventionModelBuilder.Entity( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool? shouldBeOwned, + bool fromDataAnnotation) => Entity(type, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention, shouldBeOwned); /// @@ -725,7 +739,7 @@ IConventionModel IConventionModelBuilder.Metadata /// [DebuggerStepThrough] IConventionEntityTypeBuilder? IConventionModelBuilder.Entity( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, string definingNavigationName, IConventionEntityType definingEntityType, bool fromDataAnnotation) @@ -742,7 +756,9 @@ IConventionModel IConventionModelBuilder.Metadata /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IConventionOwnedEntityTypeBuilder? IConventionModelBuilder.Owned(Type type, bool fromDataAnnotation) + IConventionOwnedEntityTypeBuilder? IConventionModelBuilder.Owned( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation) => Owned(type, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -752,7 +768,9 @@ IConventionModel IConventionModelBuilder.Metadata /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - bool IConventionModelBuilder.IsIgnored(Type type, bool fromDataAnnotation) + bool IConventionModelBuilder.IsIgnored( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation) => IsIgnored(type, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -772,7 +790,9 @@ bool IConventionModelBuilder.IsIgnored(string name, bool fromDataAnnotation) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IConventionModelBuilder? IConventionModelBuilder.Ignore(Type type, bool fromDataAnnotation) + IConventionModelBuilder? IConventionModelBuilder.Ignore( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation) => Ignore(type, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -803,7 +823,9 @@ bool IConventionModelBuilder.IsIgnored(string name, bool fromDataAnnotation) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - bool IConventionModelBuilder.CanIgnore(Type type, bool fromDataAnnotation) + bool IConventionModelBuilder.CanIgnore( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation) => CanIgnore(type, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// diff --git a/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs b/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs index 16fd8661558..4fe06855d01 100644 --- a/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata.Internal; /// @@ -340,7 +342,7 @@ public virtual bool CanSetAfterSave(PropertySaveBehavior? behavior, Configuratio /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalPropertyBuilder? HasValueGenerator( - Type? valueGeneratorType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? valueGeneratorType, ConfigurationSource configurationSource) { if (valueGeneratorType == null) @@ -398,7 +400,7 @@ public virtual bool CanSetAfterSave(PropertySaveBehavior? behavior, Configuratio /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalPropertyBuilder? HasValueGeneratorFactory( - Type? factory, + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? factory, ConfigurationSource configurationSource) { if (CanSetValueGeneratorFactory(factory, configurationSource)) @@ -431,7 +433,7 @@ public virtual bool CanSetValueGenerator( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool CanSetValueGeneratorFactory( - Type? factory, + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? factory, ConfigurationSource? configurationSource) => configurationSource.Overrides(Metadata.GetValueGeneratorFactoryConfigurationSource()) || (Metadata[CoreAnnotationNames.ValueGeneratorFactory] == null @@ -508,7 +510,9 @@ public virtual bool CanSetConversion(Type? providerClrType, ConfigurationSource? /// 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 InternalPropertyBuilder? HasConverter(Type? converterType, ConfigurationSource configurationSource) + public virtual InternalPropertyBuilder? HasConverter( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType, + ConfigurationSource configurationSource) { if (CanSetConverter(converterType, configurationSource)) { @@ -527,7 +531,9 @@ public virtual bool CanSetConversion(Type? providerClrType, ConfigurationSource? /// 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 CanSetConverter(Type? converterType, ConfigurationSource? configurationSource) + public virtual bool CanSetConverter( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType, + ConfigurationSource? configurationSource) => configurationSource.Overrides(Metadata.GetValueConverterConfigurationSource()) || (Metadata[CoreAnnotationNames.ValueConverter] == null && (Type?)Metadata[CoreAnnotationNames.ValueConverterType] == converterType); @@ -617,7 +623,7 @@ public virtual bool CanSetValueComparer(ValueComparer? comparer, ConfigurationSo /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalPropertyBuilder? HasValueComparer( - Type? comparerType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, ConfigurationSource configurationSource) { if (CanSetValueComparer(comparerType, configurationSource)) @@ -685,7 +691,7 @@ public virtual bool CanSetProviderValueComparer(ValueComparer? comparer, Configu /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual InternalPropertyBuilder? HasProviderValueComparer( - Type? comparerType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, ConfigurationSource configurationSource) { if (CanSetProviderValueComparer(comparerType, configurationSource)) @@ -704,7 +710,9 @@ public virtual bool CanSetProviderValueComparer(ValueComparer? comparer, Configu /// 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 CanSetProviderValueComparer(Type? comparerType, ConfigurationSource? configurationSource) + public virtual bool CanSetProviderValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + ConfigurationSource? configurationSource) => configurationSource.Overrides(Metadata.GetProviderValueComparerConfigurationSource()) || (Metadata[CoreAnnotationNames.ProviderValueComparer] == null && (Type?)Metadata[CoreAnnotationNames.ProviderValueComparerType] == comparerType); @@ -1101,7 +1109,9 @@ bool IConventionPropertyBuilder.CanSetAfterSave(PropertySaveBehavior? behavior, /// 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. /// - IConventionPropertyBuilder? IConventionPropertyBuilder.HasValueGenerator(Type? valueGeneratorType, bool fromDataAnnotation) + IConventionPropertyBuilder? IConventionPropertyBuilder.HasValueGenerator( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? valueGeneratorType, + bool fromDataAnnotation) => HasValueGenerator( valueGeneratorType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); @@ -1132,7 +1142,7 @@ bool IConventionPropertyBuilder.CanSetValueGenerator(Func IConventionPropertyBuilder? IConventionPropertyBuilder.HasValueGeneratorFactory( - Type? valueGeneratorFactoryType, + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? valueGeneratorFactoryType, bool fromDataAnnotation) => HasValueGeneratorFactory( valueGeneratorFactoryType, @@ -1144,7 +1154,9 @@ bool IConventionPropertyBuilder.CanSetValueGenerator(Func - bool IConventionPropertyBuilder.CanSetValueGeneratorFactory(Type? valueGeneratorFactoryType, bool fromDataAnnotation) + bool IConventionPropertyBuilder.CanSetValueGeneratorFactory( + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? valueGeneratorFactoryType, + bool fromDataAnnotation) => CanSetValueGeneratorFactory( valueGeneratorFactoryType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); @@ -1173,7 +1185,9 @@ bool IConventionPropertyBuilder.CanSetConversion(ValueConverter? converter, bool /// 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. /// - IConventionPropertyBuilder? IConventionPropertyBuilder.HasConverter(Type? converterType, bool fromDataAnnotation) + IConventionPropertyBuilder? IConventionPropertyBuilder.HasConverter( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType, + bool fromDataAnnotation) => HasConverter(converterType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -1182,7 +1196,9 @@ bool IConventionPropertyBuilder.CanSetConversion(ValueConverter? converter, bool /// 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 IConventionPropertyBuilder.CanSetConverter(Type? converterType, bool fromDataAnnotation) + bool IConventionPropertyBuilder.CanSetConverter( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType, + bool fromDataAnnotation) => CanSetConverter(converterType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -1235,7 +1251,9 @@ bool IConventionPropertyBuilder.CanSetValueComparer(ValueComparer? comparer, boo /// 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. /// - IConventionPropertyBuilder? IConventionPropertyBuilder.HasValueComparer(Type? comparerType, bool fromDataAnnotation) + IConventionPropertyBuilder? IConventionPropertyBuilder.HasValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation) => HasValueComparer(comparerType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -1244,7 +1262,9 @@ bool IConventionPropertyBuilder.CanSetValueComparer(ValueComparer? comparer, boo /// 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 IConventionPropertyBuilder.CanSetValueComparer(Type? comparerType, bool fromDataAnnotation) + bool IConventionPropertyBuilder.CanSetValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation) => CanSetValueComparer(comparerType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -1271,7 +1291,9 @@ bool IConventionPropertyBuilder.CanSetProviderValueComparer(ValueComparer? compa /// 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. /// - IConventionPropertyBuilder? IConventionPropertyBuilder.HasProviderValueComparer(Type? comparerType, bool fromDataAnnotation) + IConventionPropertyBuilder? IConventionPropertyBuilder.HasProviderValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation) => HasProviderValueComparer(comparerType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -1280,7 +1302,9 @@ bool IConventionPropertyBuilder.CanSetProviderValueComparer(ValueComparer? compa /// 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 IConventionPropertyBuilder.CanSetProviderValueComparer(Type? comparerType, bool fromDataAnnotation) + bool IConventionPropertyBuilder.CanSetProviderValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation) => CanSetProviderValueComparer( comparerType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); } diff --git a/src/EFCore/Metadata/Internal/MemberClassifier.cs b/src/EFCore/Metadata/Internal/MemberClassifier.cs index fbe414e4727..f2d23b5bfdd 100644 --- a/src/EFCore/Metadata/Internal/MemberClassifier.cs +++ b/src/EFCore/Metadata/Internal/MemberClassifier.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.Internal; @@ -134,7 +135,7 @@ is not Dictionary> inverseCandidatesLookup } private bool IsCandidateNavigationPropertyType( - Type targetType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type targetType, MemberInfo memberInfo, Model model, out bool? shouldBeOwned) diff --git a/src/EFCore/Metadata/Internal/Model.cs b/src/EFCore/Metadata/Internal/Model.cs index e1a419d65a6..e05b93e0236 100644 --- a/src/EFCore/Metadata/Internal/Model.cs +++ b/src/EFCore/Metadata/Internal/Model.cs @@ -22,6 +22,7 @@ public class Model : ConventionAnnotatable, IMutableModel, IConventionModel, IRu /// 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. /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] public static readonly Type DefaultPropertyBagType = typeof(Dictionary); private readonly SortedDictionary _entityTypes = new(StringComparer.Ordinal); @@ -158,7 +159,7 @@ public virtual IEnumerable GetEntityTypes() /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual EntityType? AddEntityType( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, bool owned, ConfigurationSource configurationSource) { @@ -177,7 +178,7 @@ public virtual IEnumerable GetEntityTypes() /// public virtual EntityType? AddEntityType( string name, - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, bool owned, ConfigurationSource configurationSource) { @@ -360,7 +361,7 @@ private static void AssertCanRemove(EntityType entityType) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual EntityType? AddEntityType( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, string definingNavigationName, EntityType definingEntityType, ConfigurationSource configurationSource) @@ -496,7 +497,7 @@ public virtual IEnumerable GetEntityTypes(string name) /// 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 IsShared(Type type) + public virtual bool IsShared([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type) => FindIsSharedConfigurationSource(type) != null || Configuration?.GetConfigurationType(type) == TypeConfigurationType.SharedTypeEntityType; @@ -601,7 +602,7 @@ public virtual bool IsIgnored(Type type) /// 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 IsIgnoredType(Type type) + public virtual bool IsIgnoredType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type) => Configuration?.GetConfigurationType(type) == TypeConfigurationType.Ignored; /// @@ -654,7 +655,7 @@ public virtual IEnumerable GetTypeMappingConfiguratio /// 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 IsOwned(Type type) + public virtual bool IsOwned([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type) => FindIsOwnedConfigurationSource(type) != null || Configuration?.GetConfigurationType(type) == TypeConfigurationType.OwnedEntityType; @@ -1156,7 +1157,7 @@ void IMutableModel.SetChangeTrackingStrategy(ChangeTrackingStrategy? changeTrack /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IEntityType? IModel.FindEntityType(Type type) + IEntityType? IModel.FindEntityType([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) => FindEntityType(type); /// @@ -1311,7 +1312,7 @@ IMutableEntityType IMutableModel.AddEntityType(string name) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IMutableEntityType IMutableModel.AddEntityType(Type type) + IMutableEntityType IMutableModel.AddEntityType([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) => AddEntityType(type, owned: false, ConfigurationSource.Explicit)!; /// @@ -1321,7 +1322,9 @@ IMutableEntityType IMutableModel.AddEntityType(Type type) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IConventionEntityType? IConventionModel.AddEntityType(Type type, bool fromDataAnnotation) + IConventionEntityType? IConventionModel.AddEntityType( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation) => AddEntityType(type, owned: false, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -1331,7 +1334,9 @@ IMutableEntityType IMutableModel.AddEntityType(Type type) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IMutableEntityType IMutableModel.AddEntityType(string name, Type type) + IMutableEntityType IMutableModel.AddEntityType( + string name, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) => AddEntityType(name, type, owned: false, ConfigurationSource.Explicit)!; /// @@ -1341,7 +1346,10 @@ IMutableEntityType IMutableModel.AddEntityType(string name, Type type) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IConventionEntityType? IConventionModel.AddEntityType(string name, Type type, bool fromDataAnnotation) + IConventionEntityType? IConventionModel.AddEntityType( + string name, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation) => AddEntityType( name, type, owned: false, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); @@ -1383,7 +1391,7 @@ IMutableEntityType IMutableModel.AddEntityType( /// [DebuggerStepThrough] IMutableEntityType IMutableModel.AddEntityType( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, string definingNavigationName, IMutableEntityType definingEntityType) => AddEntityType(type, definingNavigationName, (EntityType)definingEntityType, ConfigurationSource.Explicit)!; @@ -1397,7 +1405,7 @@ IMutableEntityType IMutableModel.AddEntityType( [Obsolete] // The interface didn't mark method obsolete [DebuggerStepThrough] IConventionEntityType? IConventionModel.AddEntityType( - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, string definingNavigationName, IConventionEntityType definingEntityType, bool fromDataAnnotation) @@ -1432,7 +1440,7 @@ IMutableEntityType IMutableModel.AddOwnedEntityType(string name) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IMutableEntityType IMutableModel.AddOwnedEntityType(Type type) + IMutableEntityType IMutableModel.AddOwnedEntityType([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) => AddEntityType(type, owned: true, ConfigurationSource.Explicit)!; /// @@ -1442,7 +1450,9 @@ IMutableEntityType IMutableModel.AddOwnedEntityType(Type type) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IConventionEntityType? IConventionModel.AddOwnedEntityType(Type type, bool fromDataAnnotation) + IConventionEntityType? IConventionModel.AddOwnedEntityType( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + bool fromDataAnnotation) => AddEntityType(type, owned: true, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -1452,7 +1462,9 @@ IMutableEntityType IMutableModel.AddOwnedEntityType(Type type) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IMutableEntityType IMutableModel.AddOwnedEntityType(string name, Type type) + IMutableEntityType IMutableModel.AddOwnedEntityType( + string name, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) => AddEntityType(name, type, owned: true, ConfigurationSource.Explicit)!; /// @@ -1462,7 +1474,9 @@ IMutableEntityType IMutableModel.AddOwnedEntityType(string name, Type type) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - IConventionEntityType? IConventionModel.AddOwnedEntityType(string name, Type type, bool fromDataAnnotation) + IConventionEntityType? IConventionModel.AddOwnedEntityType( + string name, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, bool fromDataAnnotation) => AddEntityType( name, type, owned: true, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); diff --git a/src/EFCore/Metadata/Internal/ModelConfiguration.cs b/src/EFCore/Metadata/Internal/ModelConfiguration.cs index 4b9f82c7bf5..d0badc2e69e 100644 --- a/src/EFCore/Metadata/Internal/ModelConfiguration.cs +++ b/src/EFCore/Metadata/Internal/ModelConfiguration.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Dynamic; namespace Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -83,14 +84,15 @@ public virtual ModelConfiguration Validate() /// 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 TypeConfigurationType? GetConfigurationType(Type type) + public virtual TypeConfigurationType? GetConfigurationType( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type) { Type? configuredType = null; return GetConfigurationType(type, null, ref configuredType); } private TypeConfigurationType? GetConfigurationType( - Type type, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type, TypeConfigurationType? previousConfiguration, ref Type? previousType, bool getBaseTypes = true) diff --git a/src/EFCore/Metadata/Internal/Navigation.cs b/src/EFCore/Metadata/Internal/Navigation.cs index f87c1b7e809..bfab5db1871 100644 --- a/src/EFCore/Metadata/Internal/Navigation.cs +++ b/src/EFCore/Metadata/Internal/Navigation.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; namespace Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -43,6 +44,7 @@ public Navigation( /// 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. /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] public override Type ClrType => this.GetIdentifyingMemberInfo()?.GetMemberType() ?? (((IReadOnlyNavigation)this).IsCollection diff --git a/src/EFCore/Metadata/Internal/Property.cs b/src/EFCore/Metadata/Internal/Property.cs index 4a9b6abcb3a..cb4b1d6dd51 100644 --- a/src/EFCore/Metadata/Internal/Property.cs +++ b/src/EFCore/Metadata/Internal/Property.cs @@ -35,7 +35,7 @@ public class Property : PropertyBase, IMutableProperty, IConventionProperty, IPr /// public Property( string name, - Type clrType, + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] Type clrType, PropertyInfo? propertyInfo, FieldInfo? fieldInfo, EntityType declaringEntityType, @@ -76,6 +76,7 @@ public override TypeBase DeclaringType /// 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. /// + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] public override Type ClrType { get; } /// @@ -538,7 +539,7 @@ public virtual PropertySaveBehavior GetAfterSaveBehavior() /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Type? SetValueGeneratorFactory( - Type? factoryType, + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? factoryType, ConfigurationSource configurationSource) { if (factoryType != null) @@ -620,7 +621,7 @@ public virtual PropertySaveBehavior GetAfterSaveBehavior() /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Type? SetValueConverter( - Type? converterType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType, ConfigurationSource configurationSource) { ValueConverter? converter = null; @@ -782,7 +783,10 @@ public virtual CoreTypeMapping? TypeMapping /// 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 Type? SetValueComparer(Type? comparerType, ConfigurationSource configurationSource) + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + public virtual Type? SetValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + ConfigurationSource configurationSource) { ValueComparer? comparer = null; if (comparerType != null) @@ -881,7 +885,10 @@ public virtual CoreTypeMapping? TypeMapping /// 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 Type? SetProviderValueComparer(Type? comparerType, ConfigurationSource configurationSource) + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + public virtual Type? SetProviderValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + ConfigurationSource configurationSource) { ValueComparer? comparer = null; if (comparerType != null) @@ -1546,7 +1553,8 @@ void IMutableProperty.SetValueGeneratorFactory(Func [DebuggerStepThrough] - void IMutableProperty.SetValueGeneratorFactory(Type? valueGeneratorFactory) + void IMutableProperty.SetValueGeneratorFactory( + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? valueGeneratorFactory) => SetValueGeneratorFactory(valueGeneratorFactory, ConfigurationSource.Explicit); /// @@ -1557,7 +1565,7 @@ void IMutableProperty.SetValueGeneratorFactory(Type? valueGeneratorFactory) /// [DebuggerStepThrough] Type? IConventionProperty.SetValueGeneratorFactory( - Type? valueGeneratorFactory, + [DynamicallyAccessedMembers(ValueGeneratorFactory.DynamicallyAccessedMemberTypes)] Type? valueGeneratorFactory, bool fromDataAnnotation) => SetValueGeneratorFactory( valueGeneratorFactory, @@ -1592,7 +1600,7 @@ void IMutableProperty.SetValueConverter(ValueConverter? converter) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - void IMutableProperty.SetValueConverter(Type? converterType) + void IMutableProperty.SetValueConverter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType) => SetValueConverter(converterType, ConfigurationSource.Explicit); /// @@ -1602,7 +1610,9 @@ void IMutableProperty.SetValueConverter(Type? converterType) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - Type? IConventionProperty.SetValueConverter(Type? converterType, bool fromDataAnnotation) + Type? IConventionProperty.SetValueConverter( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? converterType, + bool fromDataAnnotation) => SetValueConverter( converterType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); @@ -1658,7 +1668,7 @@ void IMutableProperty.SetValueComparer(ValueComparer? comparer) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - void IMutableProperty.SetValueComparer(Type? comparerType) + void IMutableProperty.SetValueComparer([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType) => SetValueComparer(comparerType, ConfigurationSource.Explicit); /// @@ -1668,7 +1678,10 @@ void IMutableProperty.SetValueComparer(Type? comparerType) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - Type? IConventionProperty.SetValueComparer(Type? comparerType, bool fromDataAnnotation) + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type? IConventionProperty.SetValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation) => SetValueComparer( comparerType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); @@ -1721,7 +1734,8 @@ void IMutableProperty.SetProviderValueComparer(ValueComparer? comparer) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - void IMutableProperty.SetProviderValueComparer(Type? comparerType) + void IMutableProperty.SetProviderValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType) => SetProviderValueComparer(comparerType, ConfigurationSource.Explicit); /// @@ -1731,7 +1745,10 @@ void IMutableProperty.SetProviderValueComparer(Type? comparerType) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - Type? IConventionProperty.SetProviderValueComparer(Type? comparerType, bool fromDataAnnotation) + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type? IConventionProperty.SetProviderValueComparer( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type? comparerType, + bool fromDataAnnotation) => SetProviderValueComparer( comparerType, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); diff --git a/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs b/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs index 94049e13ade..c822c73358d 100644 --- a/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs +++ b/src/EFCore/Metadata/Internal/PropertyAccessorsFactory.cs @@ -56,7 +56,7 @@ private static Func CreateCurrentValueGetter { currentValueExpression = Expression.Call( entryParameter, - InternalEntityEntry.ReadShadowValueMethod.MakeGenericMethod(typeof(TProperty)), + InternalEntityEntry.MakeReadShadowValueMethod(typeof(TProperty)), Expression.Constant(shadowIndex)); } else @@ -93,7 +93,7 @@ private static Func CreateCurrentValueGetter Expression.Constant(default(TProperty), typeof(TProperty))), Expression.Call( entryParameter, - InternalEntityEntry.ReadStoreGeneratedValueMethod.MakeGenericMethod(typeof(TProperty)), + InternalEntityEntry.MakeReadStoreGeneratedValueMethod(typeof(TProperty)), Expression.Constant(storeGeneratedIndex)), currentValueExpression); } @@ -106,7 +106,7 @@ private static Func CreateCurrentValueGetter Expression.Constant(default(TProperty), typeof(TProperty))), Expression.Call( entryParameter, - InternalEntityEntry.ReadTemporaryValueMethod.MakeGenericMethod(typeof(TProperty)), + InternalEntityEntry.MakeReadTemporaryValueMethod(typeof(TProperty)), Expression.Constant(storeGeneratedIndex)), currentValueExpression); } @@ -127,7 +127,7 @@ private static Func CreateOriginalValueGetter= 0 ? Expression.Call( entryParameter, - InternalEntityEntry.ReadOriginalValueMethod.MakeGenericMethod(typeof(TProperty)), + InternalEntityEntry.MakeReadOriginalValueMethod(typeof(TProperty)), Expression.Constant(property), Expression.Constant(originalValuesIndex)) : Expression.Block( @@ -152,12 +152,12 @@ private static Func CreateRelationshipSnapshotGetter= 0 ? Expression.Call( entryParameter, - InternalEntityEntry.ReadRelationshipSnapshotValueMethod.MakeGenericMethod(typeof(TProperty)), + InternalEntityEntry.MakeReadRelationshipSnapshotValueMethod(typeof(TProperty)), Expression.Constant(propertyBase), Expression.Constant(relationshipIndex)) : Expression.Call( entryParameter, - InternalEntityEntry.GetCurrentValueMethod.MakeGenericMethod(typeof(TProperty)), + InternalEntityEntry.MakeGetCurrentValueMethod(typeof(TProperty)), Expression.Constant(propertyBase)), updateParameter) .Compile(); diff --git a/src/EFCore/Metadata/Internal/PropertyBase.cs b/src/EFCore/Metadata/Internal/PropertyBase.cs index 0a604920be5..7339cd44b21 100644 --- a/src/EFCore/Metadata/Internal/PropertyBase.cs +++ b/src/EFCore/Metadata/Internal/PropertyBase.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Internal; @@ -338,6 +339,7 @@ private void UpdateFieldInfoConfigurationSource(ConfigurationSource configuratio /// 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. /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] public abstract Type ClrType { get; } /// diff --git a/src/EFCore/Metadata/Internal/ServiceProperty.cs b/src/EFCore/Metadata/Internal/ServiceProperty.cs index fbf58a01767..6e89206103c 100644 --- a/src/EFCore/Metadata/Internal/ServiceProperty.cs +++ b/src/EFCore/Metadata/Internal/ServiceProperty.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; namespace Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -64,6 +65,7 @@ public override TypeBase DeclaringType /// 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. /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] public override Type ClrType { get; } /// diff --git a/src/EFCore/Metadata/Internal/TypeBase.cs b/src/EFCore/Metadata/Internal/TypeBase.cs index 2337e4999ce..1041ff83716 100644 --- a/src/EFCore/Metadata/Internal/TypeBase.cs +++ b/src/EFCore/Metadata/Internal/TypeBase.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; namespace Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -29,7 +30,10 @@ private readonly Dictionary _ignoredMembers /// 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. /// - protected TypeBase(Type type, Model model, ConfigurationSource configurationSource) + protected TypeBase( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + Model model, + ConfigurationSource configurationSource) { Check.NotNull(model, nameof(model)); @@ -47,7 +51,11 @@ protected TypeBase(Type type, Model model, ConfigurationSource configurationSour /// 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. /// - protected TypeBase(string name, Type type, Model model, ConfigurationSource configurationSource) + protected TypeBase( + string name, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + Model model, + ConfigurationSource configurationSource) { Name = name; ClrType = type; @@ -63,6 +71,7 @@ protected TypeBase(string name, Type type, Model model, ConfigurationSource conf /// 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. /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] public virtual Type ClrType { [DebuggerStepThrough] get; } /// @@ -376,6 +385,7 @@ IModel ITypeBase.Model /// 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. /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type IReadOnlyTypeBase.ClrType { [DebuggerStepThrough] diff --git a/src/EFCore/Metadata/Internal/TypeIdentity.cs b/src/EFCore/Metadata/Internal/TypeIdentity.cs index 8f7a07dde88..8afe68643d0 100644 --- a/src/EFCore/Metadata/Internal/TypeIdentity.cs +++ b/src/EFCore/Metadata/Internal/TypeIdentity.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.Metadata.Internal; /// @@ -33,7 +35,7 @@ public TypeIdentity(string name) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - public TypeIdentity(string name, Type type) + public TypeIdentity(string name, [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) { Name = name; Type = type; @@ -47,7 +49,7 @@ public TypeIdentity(string name, Type type) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [DebuggerStepThrough] - public TypeIdentity(Type type, Model model) + public TypeIdentity([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, Model model) { Name = model.GetDisplayName(type); Type = type; @@ -68,6 +70,7 @@ public TypeIdentity(Type type, Model model) /// 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. /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] public Type? Type { [DebuggerStepThrough] get; } /// diff --git a/src/EFCore/Metadata/RuntimeEntityType.cs b/src/EFCore/Metadata/RuntimeEntityType.cs index 48150417c96..69a18b52228 100644 --- a/src/EFCore/Metadata/RuntimeEntityType.cs +++ b/src/EFCore/Metadata/RuntimeEntityType.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -42,6 +43,7 @@ private readonly SortedDictionary _triggers private RuntimeKey? _primaryKey; private readonly bool _hasSharedClrType; + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] private readonly Type _clrType; private readonly RuntimeEntityType? _baseType; private readonly SortedSet _directlyDerivedTypes = new(EntityTypeFullNameComparer.Instance); @@ -73,7 +75,7 @@ private readonly SortedDictionary _triggers [EntityFrameworkInternal] public RuntimeEntityType( string name, - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, bool sharedClrType, RuntimeModel model, RuntimeEntityType? baseType, @@ -836,7 +838,9 @@ public virtual InstantiationBinding? ServiceOnlyConstructorBinding /// /// The type to look for the indexer on. /// An indexer property or . - public static PropertyInfo? FindIndexerProperty(Type type) + public static PropertyInfo? FindIndexerProperty( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] + Type type) => type.FindIndexerProperty(); /// @@ -859,6 +863,7 @@ public virtual DebugView DebugView () => ((IReadOnlyEntityType)this).ToDebugString(MetadataDebugStringOptions.LongDefault)); /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type IReadOnlyTypeBase.ClrType { [DebuggerStepThrough] diff --git a/src/EFCore/Metadata/RuntimeModel.cs b/src/EFCore/Metadata/RuntimeModel.cs index 75968bbab15..9ca509cecb1 100644 --- a/src/EFCore/Metadata/RuntimeModel.cs +++ b/src/EFCore/Metadata/RuntimeModel.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -62,7 +63,7 @@ public virtual void SetSkipDetectChanges(bool skipDetectChanges) /// The new entity type. public virtual RuntimeEntityType AddEntityType( string name, - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, RuntimeEntityType? baseType = null, bool sharedClrType = false, string? discriminatorProperty = null, @@ -173,7 +174,7 @@ public virtual RuntimeTypeMappingConfiguration AddTypeMappingConfiguration( private string GetDisplayName(Type type) => _clrTypeNameMap.GetOrAdd(type, t => t.DisplayName()); - private PropertyInfo? FindIndexerPropertyInfo(Type type) + private PropertyInfo? FindIndexerPropertyInfo([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) => _indexerPropertyInfoMap.GetOrAdd(type, type.FindIndexerProperty()); /// @@ -240,7 +241,7 @@ bool IModel.IsIndexerMethod(MethodInfo methodInfo) /// [DebuggerStepThrough] - IEntityType? IModel.FindEntityType(Type type) + IEntityType? IModel.FindEntityType([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) => FindEntityType(type); /// @@ -289,7 +290,7 @@ IEnumerable IModel.FindEntityTypes(Type type) /// [DebuggerStepThrough] - bool IReadOnlyModel.IsShared(Type type) + bool IReadOnlyModel.IsShared([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type) => _sharedTypes.ContainsKey(type); /// diff --git a/src/EFCore/Metadata/RuntimeNavigation.cs b/src/EFCore/Metadata/RuntimeNavigation.cs index 4888522a1e8..427292af81a 100644 --- a/src/EFCore/Metadata/RuntimeNavigation.cs +++ b/src/EFCore/Metadata/RuntimeNavigation.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -46,6 +47,7 @@ public RuntimeNavigation( /// /// Gets the type of value that this navigation holds. /// + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] protected override Type ClrType { get; } /// diff --git a/src/EFCore/Metadata/RuntimeProperty.cs b/src/EFCore/Metadata/RuntimeProperty.cs index 941a46cc7b5..44065cc6ae2 100644 --- a/src/EFCore/Metadata/RuntimeProperty.cs +++ b/src/EFCore/Metadata/RuntimeProperty.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -107,6 +108,7 @@ public RuntimeProperty( /// /// Gets the type of value that this property-like object holds. /// + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] protected override Type ClrType { get; } /// diff --git a/src/EFCore/Metadata/RuntimePropertyBase.cs b/src/EFCore/Metadata/RuntimePropertyBase.cs index 421970721ca..1073786388f 100644 --- a/src/EFCore/Metadata/RuntimePropertyBase.cs +++ b/src/EFCore/Metadata/RuntimePropertyBase.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -59,6 +60,7 @@ protected RuntimePropertyBase( /// /// Gets the type of value that this property-like object holds. /// + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] protected abstract Type ClrType { get; } /// @@ -117,6 +119,7 @@ PropertyIndexes IRuntimePropertyBase.PropertyIndexes } /// + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type IReadOnlyPropertyBase.ClrType { [DebuggerStepThrough] diff --git a/src/EFCore/Metadata/RuntimeServiceProperty.cs b/src/EFCore/Metadata/RuntimeServiceProperty.cs index c80efaa8e89..09f6e33f947 100644 --- a/src/EFCore/Metadata/RuntimeServiceProperty.cs +++ b/src/EFCore/Metadata/RuntimeServiceProperty.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; namespace Microsoft.EntityFrameworkCore.Metadata; @@ -45,6 +46,7 @@ public RuntimeServiceProperty( /// /// Gets the type of value that this property-like object holds. /// + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] protected override Type ClrType { get; } /// diff --git a/src/EFCore/Metadata/RuntimeSkipNavigation.cs b/src/EFCore/Metadata/RuntimeSkipNavigation.cs index 496beebacf6..f5093298837 100644 --- a/src/EFCore/Metadata/RuntimeSkipNavigation.cs +++ b/src/EFCore/Metadata/RuntimeSkipNavigation.cs @@ -70,6 +70,7 @@ public RuntimeSkipNavigation( /// /// Gets the type of value that this navigation holds. /// + [DynamicallyAccessedMembers(IProperty.DynamicallyAccessedMemberTypes)] protected override Type ClrType { get; } /// diff --git a/src/EFCore/ModelBuilder.cs b/src/EFCore/ModelBuilder.cs index c3c1863ba67..aa3208c1d05 100644 --- a/src/EFCore/ModelBuilder.cs +++ b/src/EFCore/ModelBuilder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore; @@ -145,7 +146,8 @@ IConventionModelBuilder IInfrastructure.Instance /// /// The entity type to be configured. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder Entity() + public virtual EntityTypeBuilder Entity< + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>() where TEntity : class => new(Builder.Entity(typeof(TEntity), ConfigurationSource.Explicit, shouldBeOwned: false)!.Metadata); @@ -169,7 +171,9 @@ public virtual EntityTypeBuilder Entity() /// The CLR type of the entity type to be configured. /// The name of the entity type to be configured. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder SharedTypeEntity(string name) + public virtual EntityTypeBuilder SharedTypeEntity< + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>( + string name) where TEntity : class { Check.NotEmpty(name, nameof(name)); @@ -186,7 +190,7 @@ public virtual EntityTypeBuilder SharedTypeEntity(string name) /// /// The entity type to be configured. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder Entity(Type type) + public virtual EntityTypeBuilder Entity([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) { Check.NotNull(type, nameof(type)); @@ -230,7 +234,9 @@ public virtual EntityTypeBuilder Entity(string name) /// The name of the entity type to be configured. /// The CLR type of the entity type to be configured. /// An object that can be used to configure the entity type. - public virtual EntityTypeBuilder SharedTypeEntity(string name, Type type) + public virtual EntityTypeBuilder SharedTypeEntity( + string name, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) { Check.NotEmpty(name, nameof(name)); Check.NotNull(type, nameof(type)); @@ -258,7 +264,8 @@ public virtual EntityTypeBuilder SharedTypeEntity(string name, Type type) /// /// The same instance so that additional configuration calls can be chained. /// - public virtual ModelBuilder Entity(Action> buildAction) + public virtual ModelBuilder Entity<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>( + Action> buildAction) where TEntity : class { Check.NotNull(buildAction, nameof(buildAction)); @@ -296,7 +303,7 @@ public virtual ModelBuilder Entity(Action> b /// /// The same instance so that additional configuration calls can be chained. /// - public virtual ModelBuilder SharedTypeEntity( + public virtual ModelBuilder SharedTypeEntity<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>( string name, Action> buildAction) where TEntity : class @@ -327,7 +334,9 @@ public virtual ModelBuilder SharedTypeEntity( /// /// The same instance so that additional configuration calls can be chained. /// - public virtual ModelBuilder Entity(Type type, Action buildAction) + public virtual ModelBuilder Entity( + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, + Action buildAction) { Check.NotNull(buildAction, nameof(buildAction)); @@ -395,7 +404,7 @@ public virtual ModelBuilder Entity(string name, Action buildA /// public virtual ModelBuilder SharedTypeEntity( string name, - Type type, + [DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type, Action buildAction) { Check.NotNull(type, nameof(type)); @@ -417,7 +426,7 @@ public virtual ModelBuilder SharedTypeEntity( /// /// The same instance so that additional configuration calls can be chained. /// - public virtual ModelBuilder Ignore() + public virtual ModelBuilder Ignore<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>() where TEntity : class => Ignore(typeof(TEntity)); @@ -432,7 +441,7 @@ public virtual ModelBuilder Ignore() /// /// The same instance so that additional configuration calls can be chained. /// - public virtual ModelBuilder Ignore(Type type) + public virtual ModelBuilder Ignore([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) { Check.NotNull(type, nameof(type)); @@ -472,7 +481,8 @@ public virtual ModelBuilder Ignore(string typeName) /// /// The same instance so that additional configuration calls can be chained. /// - public virtual ModelBuilder ApplyConfiguration(IEntityTypeConfiguration configuration) + public virtual ModelBuilder ApplyConfiguration + <[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] TEntity>(IEntityTypeConfiguration configuration) where TEntity : class { Check.NotNull(configuration, nameof(configuration)); @@ -494,6 +504,7 @@ public virtual ModelBuilder ApplyConfiguration(IEntityTypeConfiguration /// /// The same instance so that additional configuration calls can be chained. /// + [RequiresUnreferencedCode("This API isn't safe for trimming, since it searches for types in an arbitrary assembly.")] public virtual ModelBuilder ApplyConfigurationsFromAssembly( Assembly assembly, Func? predicate = null) @@ -541,7 +552,7 @@ public virtual ModelBuilder ApplyConfigurationsFromAssembly( /// See Owned types in EF Core for more information and examples. /// /// The entity type to be configured. - public virtual OwnedEntityTypeBuilder Owned() + public virtual OwnedEntityTypeBuilder Owned<[DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] T>() where T : class { Builder.Owned(typeof(T), ConfigurationSource.Explicit); @@ -557,7 +568,7 @@ public virtual OwnedEntityTypeBuilder Owned() /// See Owned types in EF Core for more information and examples. /// /// The entity type to be configured. - public virtual OwnedEntityTypeBuilder Owned(Type type) + public virtual OwnedEntityTypeBuilder Owned([DynamicallyAccessedMembers(IEntityType.DynamicallyAccessedMemberTypes)] Type type) { Check.NotNull(type, nameof(type)); diff --git a/src/EFCore/Query/TransparentIdentifierFactory.cs b/src/EFCore/Query/TransparentIdentifierFactory.cs index aa48b1a3462..6bbdf329929 100644 --- a/src/EFCore/Query/TransparentIdentifierFactory.cs +++ b/src/EFCore/Query/TransparentIdentifierFactory.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; namespace Microsoft.EntityFrameworkCore.Query; @@ -28,6 +29,8 @@ public static class TransparentIdentifierFactory /// The outer type of the transparent identifier. /// The inner type of the transparent identifier. /// The created transparent identifier type. + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(TransparentIdentifier<,>))] public static Type Create(Type outerType, Type innerType) => typeof(TransparentIdentifier<,>).MakeGenericType(outerType, innerType); diff --git a/src/EFCore/Storage/CoreTypeMapping.cs b/src/EFCore/Storage/CoreTypeMapping.cs index 4e34527d3ad..bc39feacff8 100644 --- a/src/EFCore/Storage/CoreTypeMapping.cs +++ b/src/EFCore/Storage/CoreTypeMapping.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore.Internal; namespace Microsoft.EntityFrameworkCore.Storage; @@ -35,7 +36,7 @@ protected readonly record struct CoreTypeMappingParameters /// Supports custom comparisons between converted provider values. /// An optional factory for creating a specific . public CoreTypeMappingParameters( - Type clrType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type clrType, ValueConverter? converter = null, ValueComparer? comparer = null, ValueComparer? keyComparer = null, @@ -53,6 +54,7 @@ public CoreTypeMappingParameters( /// /// The mapping CLR type. /// + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] public Type ClrType { get; init; } /// @@ -155,6 +157,9 @@ protected CoreTypeMapping(CoreTypeMappingParameters parameters) /// /// Gets the .NET type used in the EF model. /// + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods + | DynamicallyAccessedMemberTypes.NonPublicMethods + | DynamicallyAccessedMemberTypes.PublicProperties)] public virtual Type ClrType { get; } /// diff --git a/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs b/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs index 3d349c38094..5acd413f599 100644 --- a/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs +++ b/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Net; using System.Net.NetworkInformation; @@ -559,6 +560,8 @@ private IEnumerable FindPreferredConversions( } } - private static ValueConverterInfo GetDefaultValueConverterInfo(Type converterTypeInfo) + private static ValueConverterInfo GetDefaultValueConverterInfo( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] + Type converterTypeInfo) => (ValueConverterInfo)converterTypeInfo.GetAnyProperty("DefaultInfo")!.GetValue(null)!; } diff --git a/src/EFCore/ValueGeneration/ValueGeneratorFactory.cs b/src/EFCore/ValueGeneration/ValueGeneratorFactory.cs index 6d28afb51f1..6f2e0b8099b 100644 --- a/src/EFCore/ValueGeneration/ValueGeneratorFactory.cs +++ b/src/EFCore/ValueGeneration/ValueGeneratorFactory.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.EntityFrameworkCore.ValueGeneration; /// @@ -21,4 +23,8 @@ public abstract class ValueGeneratorFactory /// The entity type for which the value generator will be used. /// The newly created value generator. public abstract ValueGenerator Create(IProperty property, IEntityType entityType); + + internal const DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes = + System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors + | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors; } diff --git a/src/Shared/SharedTypeExtensions.cs b/src/Shared/SharedTypeExtensions.cs index c52c0720cff..f71091c39e8 100644 --- a/src/Shared/SharedTypeExtensions.cs +++ b/src/Shared/SharedTypeExtensions.cs @@ -3,6 +3,12 @@ #nullable enable +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; using System.Runtime.CompilerServices; using System.Text; @@ -45,7 +51,7 @@ public static bool IsValidEntityType(this Type type) => type.IsClass && !type.IsArray; - public static bool IsPropertyBagType(this Type type) + public static bool IsPropertyBagType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] this Type type) { if (type.IsGenericTypeDefinition) { @@ -101,7 +107,10 @@ public static bool IsAnonymousType(this Type type) && type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), inherit: false).Length > 0 && type.Name.Contains("AnonymousType"); - public static PropertyInfo? GetAnyProperty(this Type type, string name) + public static PropertyInfo? GetAnyProperty( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] + this Type type, + string name) { var props = type.GetRuntimeProperties().Where(p => p.Name == name).ToList(); if (props.Count > 1) @@ -130,7 +139,7 @@ public static Type UnwrapEnumType(this Type type) return isNullable ? MakeNullable(underlyingEnumType) : underlyingEnumType; } - public static Type GetSequenceType(this Type type) + public static Type GetSequenceType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] this Type type) { var sequenceType = TryGetSequenceType(type); if (sequenceType == null) @@ -141,11 +150,13 @@ public static Type GetSequenceType(this Type type) return sequenceType; } - public static Type? TryGetSequenceType(this Type type) + public static Type? TryGetSequenceType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] this Type type) => type.TryGetElementType(typeof(IEnumerable<>)) ?? type.TryGetElementType(typeof(IAsyncEnumerable<>)); - public static Type? TryGetElementType(this Type type, Type interfaceOrBaseType) + public static Type? TryGetElementType( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] this Type type, + Type interfaceOrBaseType) { if (type.IsGenericTypeDefinition) { @@ -275,7 +286,8 @@ public static IEnumerable GetTypesInHierarchy(this Type type) } } - public static IEnumerable GetDeclaredInterfaces(this Type type) + public static IEnumerable GetDeclaredInterfaces( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] this Type type) { var interfaces = type.GetInterfaces(); if (type.BaseType == typeof(object) @@ -284,10 +296,18 @@ public static IEnumerable GetDeclaredInterfaces(this Type type) return interfaces; } - return interfaces.Except(type.BaseType.GetInterfaces()); + return interfaces.Except(GetInterfacesSuppressed(type.BaseType)); + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070", Justification = "https://github.com/dotnet/linker/issues/2473")] + static IEnumerable GetInterfacesSuppressed(Type type) + => type.GetInterfaces(); } - public static ConstructorInfo? GetDeclaredConstructor(this Type type, Type[]? types) + public static ConstructorInfo? GetDeclaredConstructor( + [DynamicallyAccessedMembers( + DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + this Type type, + Type[]? types) { types ??= Array.Empty(); @@ -340,7 +360,14 @@ public static IEnumerable GetMembersInHierarchy(this Type type) while (currentType != null); } - public static IEnumerable GetMembersInHierarchy(this Type type, string name) + public static IEnumerable GetMembersInHierarchy( + [DynamicallyAccessedMembers( + DynamicallyAccessedMemberTypes.PublicProperties + | DynamicallyAccessedMemberTypes.NonPublicProperties + | DynamicallyAccessedMemberTypes.PublicFields + | DynamicallyAccessedMemberTypes.NonPublicFields)] + this Type type, + string name) => type.GetMembersInHierarchy().Where(m => m.Name == name); private static readonly Dictionary CommonTypeDictionary = new() @@ -366,7 +393,8 @@ public static IEnumerable GetMembersInHierarchy(this Type type, stri #pragma warning restore IDE0034 // Simplify 'default' expression }; - public static object? GetDefaultValue(this Type type) + public static object? GetDefaultValue( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] this Type type) { if (!type.IsValueType) { @@ -381,11 +409,13 @@ public static IEnumerable GetMembersInHierarchy(this Type type, stri : Activator.CreateInstance(type); } + [RequiresUnreferencedCode("Gets all types from the given assembly - unsafe for trimming")] public static IEnumerable GetConstructibleTypes(this Assembly assembly) => assembly.GetLoadableDefinedTypes().Where( t => !t.IsAbstract && !t.IsGenericTypeDefinition); + [RequiresUnreferencedCode("Gets all types from the given assembly - unsafe for trimming")] public static IEnumerable GetLoadableDefinedTypes(this Assembly assembly) { try diff --git a/test/EFCore.Trimming.Tests/EFCore.Trimming.Tests.csproj b/test/EFCore.Trimming.Tests/EFCore.Trimming.Tests.csproj index 58562d6d4ad..33e2f616fb4 100644 --- a/test/EFCore.Trimming.Tests/EFCore.Trimming.Tests.csproj +++ b/test/EFCore.Trimming.Tests/EFCore.Trimming.Tests.csproj @@ -4,7 +4,6 @@ Exe net7.0 true - partial false diff --git a/test/EFCore.Trimming.Tests/Program.cs b/test/EFCore.Trimming.Tests/Program.cs index 5a3eef1f5a8..114f9cae257 100644 --- a/test/EFCore.Trimming.Tests/Program.cs +++ b/test/EFCore.Trimming.Tests/Program.cs @@ -11,16 +11,28 @@ await ctx.Database.EnsureDeletedAsync(); await ctx.Database.EnsureCreatedAsync(); +ctx.Add(new Blog { Name = "Some Blog Name" }); +await ctx.SaveChangesAsync(); + +ctx.ChangeTracker.Clear(); + // Execute any query to make sure the basic query pipeline works -_ = ctx.Blogs.Where(b => b.Name.StartsWith("foo")).ToList(); +var blog = await ctx.Blogs.Where(b => b.Name.StartsWith("Some ")).SingleAsync(); +if (blog.Name != "Some Blog Name") +{ + throw new Exception($"Incorrect blog name ({blog.Name})"); +} Console.WriteLine("Database query executed successfully."); public class BlogContext : DbContext { + public BlogContext() + => Blogs = Set(); + private static readonly string ConnectionString; - public DbSet Blogs { get; set; } + public DbSet Blogs { get; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseSqlServer(ConnectionString);