diff --git a/Extensions/Xtensive.Orm.BulkOperations/Internals/Operation.cs b/Extensions/Xtensive.Orm.BulkOperations/Internals/Operation.cs index 306c3178ff..168ed0d643 100644 --- a/Extensions/Xtensive.Orm.BulkOperations/Internals/Operation.cs +++ b/Extensions/Xtensive.Orm.BulkOperations/Internals/Operation.cs @@ -67,11 +67,12 @@ protected void EnsureTransactionIsStarted() public QueryTranslationResult GetRequest(IQueryable query) => QueryBuilder.TranslateQuery(query); - public QueryTranslationResult GetRequest(Type type, IQueryable query) - { - var translateQueryMethod = WellKnownMembers.TranslateQueryMethod.CachedMakeGenericMethod(type); - return (QueryTranslationResult) translateQueryMethod.Invoke(QueryBuilder, new object[] {query}); - } + public QueryTranslationResult GetRequest(Type type, IQueryable query) => +#if NET8_0_OR_GREATER + (QueryTranslationResult) WellKnownMembers.TranslateQueryMethod.CachedMakeGenericMethodInvoker(type).Invoke(QueryBuilder, query); +#else + (QueryTranslationResult) WellKnownMembers.TranslateQueryMethod.CachedMakeGenericMethod(type).Invoke(QueryBuilder, new object[] {query}); +#endif public TypeInfo GetTypeInfo(Type entityType) => Session.Domain.Model.Hierarchies.SelectMany(a => a.Types).Single(a => a.UnderlyingType == entityType); diff --git a/Orm/Xtensive.Orm/IoC/ServiceContainer.cs b/Orm/Xtensive.Orm/IoC/ServiceContainer.cs index 0574bbfbb6..a6dfbc1052 100644 --- a/Orm/Xtensive.Orm/IoC/ServiceContainer.cs +++ b/Orm/Xtensive.Orm/IoC/ServiceContainer.cs @@ -29,7 +29,11 @@ public class ServiceContainer : ServiceContainerBase { private static readonly Type iServiceContainerType = typeof(IServiceContainer); +#if NET8_0_OR_GREATER + private static readonly Func> ConstructorFactory = serviceInfo => { +#else private static readonly Func> ConstructorFactory = serviceInfo => { +#endif var mappedType = serviceInfo.MappedType; var ctor = ( from c in mappedType.GetConstructors() @@ -37,7 +41,11 @@ where c.GetAttribute(AttributeSearchOptions.Inherit select c ).SingleOrDefault() ?? mappedType.GetConstructor(Array.Empty()); var @params = ctor?.GetParameters(); - return new Pair(ctor, @params); +#if NET8_0_OR_GREATER + return new(ctor is null ? null : ConstructorInvoker.Create(ctor), @params); +#else + return new(ctor, @params); +#endif }; private readonly IReadOnlyDictionary> types; @@ -45,8 +53,11 @@ select c private readonly ConcurrentDictionary> instances = new ConcurrentDictionary>(); - private readonly ConcurrentDictionary> constructorCache = - new ConcurrentDictionary>(); +#if NET8_0_OR_GREATER + private readonly ConcurrentDictionary> constructorCache = new(); +#else + private readonly ConcurrentDictionary> constructorCache = new(); +#endif private readonly ConcurrentDictionary<(Type, int), bool> creating = new ConcurrentDictionary<(Type, int), bool>(); @@ -85,7 +96,8 @@ protected virtual object CreateInstance(ServiceRegistration serviceInfo) return null; } var pInfos = cachedInfo.Second; - if (pInfos.Length == 0) { + var nArg = pInfos.Length; + if (nArg == 0) { return Activator.CreateInstance(serviceInfo.MappedType); } var managedThreadId = Environment.CurrentManagedThreadId; @@ -93,9 +105,9 @@ protected virtual object CreateInstance(ServiceRegistration serviceInfo) if (!creating.TryAdd(key, true)) { throw new ActivationException(Strings.ExRecursiveConstructorParameterDependencyIsDetected); } - var args = new object[pInfos.Length]; + var args = new object[nArg]; try { - for (var i = 0; i < pInfos.Length; i++) { + for (var i = 0; i < nArg; i++) { var type = pInfos[i].ParameterType; if (creating.ContainsKey((type, managedThreadId))) { throw new ActivationException(Strings.ExRecursiveConstructorParameterDependencyIsDetected); @@ -106,10 +118,14 @@ protected virtual object CreateInstance(ServiceRegistration serviceInfo) finally { _ = creating.TryRemove(key, out _); } +#if NET8_0_OR_GREATER + return cInfo.Invoke(args.AsSpan()); +#else return cInfo.Invoke(args); +#endif } - #endregion +#endregion #region Private \ internal methods @@ -194,17 +210,28 @@ public static IServiceContainer Create(Type containerType, object configuration, Type configurationType = configuration?.GetType(), parentType = parent?.GetType(); return (IServiceContainer) ( +#if NET8_0_OR_GREATER + FindConstructorInvoker(containerType, configurationType, parentType)?.Invoke(configuration, parent) + ?? FindConstructorInvoker(containerType, configurationType)?.Invoke(configuration) + ?? FindConstructorInvoker(containerType, parentType)?.Invoke(parent) +#else FindConstructor(containerType, configurationType, parentType)?.Invoke(new[] { configuration, parent }) ?? FindConstructor(containerType, configurationType)?.Invoke(new[] { configuration }) ?? FindConstructor(containerType, parentType)?.Invoke(new[] { parent }) +#endif ?? throw new ArgumentException(Strings.ExContainerTypeDoesNotProvideASuitableConstructor, "containerType") ); } +#if NET8_0_OR_GREATER + private static ConstructorInvoker FindConstructorInvoker(Type containerType, params Type[] argumentTypes) => + containerType.GetSingleConstructorInvokerOrDefault(argumentTypes); +#else private static ConstructorInfo FindConstructor(Type containerType, params Type[] argumentTypes) => containerType.GetSingleConstructorOrDefault(argumentTypes); +#endif - #endregion +#endregion /// /// Creates by default configuration. @@ -324,4 +351,4 @@ public override void Dispose() } } } -} \ No newline at end of file +} diff --git a/Orm/Xtensive.Orm/Modelling/PropertyAccessor.cs b/Orm/Xtensive.Orm/Modelling/PropertyAccessor.cs index 7e3316ee94..909ebf3480 100644 --- a/Orm/Xtensive.Orm/Modelling/PropertyAccessor.cs +++ b/Orm/Xtensive.Orm/Modelling/PropertyAccessor.cs @@ -174,9 +174,11 @@ private void Initialize() dependencyRootType = pa.DependencyRootType; compareCaseInsensitive = tProperty == WellKnownTypes.String && pa.CaseInsensitiveComparison; } - InnerInitializeMethodDefinition - .CachedMakeGenericMethod(tType, tProperty) - .Invoke(this, null); +#if NET8_0_OR_GREATER + InnerInitializeMethodDefinition.CachedMakeGenericMethodInvoker(tType, tProperty).Invoke(this); +#else + InnerInitializeMethodDefinition.CachedMakeGenericMethod(tType, tProperty).Invoke(this, null); +#endif } private void InnerInitialize() diff --git a/Orm/Xtensive.Orm/Orm/Linq/QueryProvider.cs b/Orm/Xtensive.Orm/Orm/Linq/QueryProvider.cs index 0370e30a6c..283875c038 100644 --- a/Orm/Xtensive.Orm/Orm/Linq/QueryProvider.cs +++ b/Orm/Xtensive.Orm/Orm/Linq/QueryProvider.cs @@ -53,12 +53,21 @@ public IQueryable CreateQuery(Expression expression) => object IQueryProvider.Execute(Expression expression) { var resultType = expression.Type; +#if NET8_0_OR_GREATER + var executeMethod = resultType.IsOfGenericInterface(WellKnownInterfaces.EnumerableOfT) + ? WellKnownMembers.QueryProvider.ExecuteSequence.CachedMakeGenericMethodInvoker(SequenceHelper.GetElementType(resultType)) + : WellKnownMembers.QueryProvider.ExecuteScalar.CachedMakeGenericMethodInvoker(resultType); + try { + return executeMethod.Invoke(this, expression); + } +#else var executeMethod = resultType.IsOfGenericInterface(WellKnownInterfaces.EnumerableOfT) ? WellKnownMembers.QueryProvider.ExecuteSequence.CachedMakeGenericMethod(SequenceHelper.GetElementType(resultType)) : WellKnownMembers.QueryProvider.ExecuteScalar.CachedMakeGenericMethod(resultType); try { - return executeMethod.Invoke(this, new object[] {expression}); + return executeMethod.Invoke(this, new object[] { expression }); } +#endif catch (TargetInvocationException e) { if (e.InnerException != null) { ExceptionDispatchInfo.Throw(e.InnerException); diff --git a/Orm/Xtensive.Orm/Orm/Providers/StorageDriver.cs b/Orm/Xtensive.Orm/Orm/Providers/StorageDriver.cs index 2678979104..363078b2d5 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/StorageDriver.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/StorageDriver.cs @@ -190,7 +190,11 @@ private static IReadOnlyCollection CreateConnectionAccess throw new NotSupportedException(string.Format(Strings.ExConnectionAccessorXHasNoParameterlessConstructor, type)); } +#if NET8_0_OR_GREATER + var accessorFactory = (Func) FactoryCreatorMethod.CachedMakeGenericMethodInvoker(type).Invoke(null); +#else var accessorFactory = (Func) FactoryCreatorMethod.CachedMakeGenericMethod(type).Invoke(null, null); +#endif instances.Add(accessorFactory()); factoriesLocal[type] = accessorFactory; } diff --git a/Orm/Xtensive.Orm/Reflection/TypeHelper.cs b/Orm/Xtensive.Orm/Reflection/TypeHelper.cs index f7c85777c3..55b449e385 100644 --- a/Orm/Xtensive.Orm/Reflection/TypeHelper.cs +++ b/Orm/Xtensive.Orm/Reflection/TypeHelper.cs @@ -53,7 +53,11 @@ public int GetHashCode((Type, Type[]) obj) private static readonly Type CompilerGeneratedAttributeType = typeof(CompilerGeneratedAttribute); private static readonly string TypeHelperNamespace = typeof(TypeHelper).Namespace; +#if NET8_0_OR_GREATER + private static readonly ConcurrentDictionary<(Type, Type[]), ConstructorInvoker> ConstructorInvokerByTypes = +#else private static readonly ConcurrentDictionary<(Type, Type[]), ConstructorInfo> ConstructorInfoByTypes = +#endif new(new TypesEqualityComparer()); private static readonly ConcurrentDictionary OrderedInterfaces = new(); @@ -68,6 +72,17 @@ public int GetHashCode((Type, Type[]) obj) private static readonly ConcurrentDictionary<(MethodInfo, Type, Type), MethodInfo> GenericMethodInstances2 = new(); +#if NET8_0_OR_GREATER + private static readonly ConcurrentDictionary<(MethodInfo, Type), MethodInvoker> GenericMethodInvokers1 = new(); + private static readonly ConcurrentDictionary<(MethodInfo, Type, Type), MethodInvoker> GenericMethodInvokers2 = new(); + + private static readonly Func<(MethodInfo genericDefinition, Type typeArgument), MethodInvoker> GenericMethodInvokerFactory1 = + key => MethodInvoker.Create(key.genericDefinition.MakeGenericMethod(key.typeArgument)); + + private static readonly Func<(MethodInfo genericDefinition, Type typeArgument1, Type typeArgument2), MethodInvoker> GenericMethodInvokerFactory2 = + key => MethodInvoker.Create(key.genericDefinition.MakeGenericMethod(key.typeArgument1, key.typeArgument2)); +#endif + private static readonly ConcurrentDictionary<(Type, Type), Type> GenericTypeInstances1 = new(); private static readonly ConcurrentDictionary<(Type, Type, Type), Type> GenericTypeInstances2 = new(); @@ -644,9 +659,17 @@ public static object Activate(this Type type, Type[] genericArguments, params ob /// The has no constructors suitable for /// -or- more than one such constructor. /// +#if NET8_0_OR_GREATER + public static ConstructorInvoker GetSingleConstructorInvoker(this Type type, Type[] argumentTypes) => + ConstructorInvokerByTypes.GetOrAdd((type, argumentTypes), + static t => ConstructorExtractor(t) is ConstructorInfo ctor + ? ConstructorInvoker.Create(ctor) + : throw new InvalidOperationException(Strings.ExGivenTypeHasNoOrMoreThanOneCtorWithGivenParameters)); +#else public static ConstructorInfo GetSingleConstructor(this Type type, Type[] argumentTypes) => ConstructorInfoByTypes.GetOrAdd((type, argumentTypes), ConstructorExtractor) ?? throw new InvalidOperationException(Strings.ExGivenTypeHasNoOrMoreThanOneCtorWithGivenParameters); +#endif /// /// Gets the public constructor of type @@ -659,8 +682,14 @@ public static ConstructorInfo GetSingleConstructor(this Type type, Type[] argume /// otherwise, . /// [CanBeNull] +#if NET8_0_OR_GREATER + public static ConstructorInvoker GetSingleConstructorInvokerOrDefault(this Type type, Type[] argumentTypes) => + ConstructorInvokerByTypes.GetOrAdd((type, argumentTypes), + static t => ConstructorExtractor(t) is ConstructorInfo ctor ? ConstructorInvoker.Create(ctor) : null); +#else public static ConstructorInfo GetSingleConstructorOrDefault(this Type type, Type[] argumentTypes) => ConstructorInfoByTypes.GetOrAdd((type, argumentTypes), ConstructorExtractor); +#endif private static readonly Func<(Type, Type[]), ConstructorInfo> ConstructorExtractor = t => { (var type, var argumentTypes) = t; @@ -920,6 +949,14 @@ public static MethodInfo CachedMakeGenericMethod(this MethodInfo genericDefiniti public static MethodInfo CachedMakeGenericMethod(this MethodInfo genericDefinition, Type typeArgument1, Type typeArgument2) => GenericMethodInstances2.GetOrAdd((genericDefinition, typeArgument1, typeArgument2), GenericMethodFactory2); +#if NET8_0_OR_GREATER + public static MethodInvoker CachedMakeGenericMethodInvoker(this MethodInfo genericDefinition, Type typeArgument) => + GenericMethodInvokers1.GetOrAdd((genericDefinition, typeArgument), GenericMethodInvokerFactory1); + + public static MethodInvoker CachedMakeGenericMethodInvoker(this MethodInfo genericDefinition, Type typeArgument1, Type typeArgument2) => + GenericMethodInvokers2.GetOrAdd((genericDefinition, typeArgument1, typeArgument2), GenericMethodInvokerFactory2); +#endif + public static Type CachedMakeGenericType(this Type genericDefinition, Type typeArgument) => GenericTypeInstances1.GetOrAdd((genericDefinition, typeArgument), GenericTypeFactory1);