public static InterceptorAggregator <TInterceptor> GetAggregator(IInterceptors interceptors) { System.Diagnostics.Debug.Assert(interceptors != null); if (AggregatorGetter is null) { SetAggregatorGetter(interceptors); } System.Diagnostics.Debug.Assert(AggregatorGetter != null); return(AggregatorGetter(interceptors));
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public DiagnosticsLogger( [NotNull] ILoggerFactory loggerFactory, [NotNull] ILoggingOptions loggingOptions, [NotNull] DiagnosticSource diagnosticSource, [NotNull] LoggingDefinitions loggingDefinitions, [CanBeNull] IInterceptors interceptors = null) { DiagnosticSource = diagnosticSource; Definitions = loggingDefinitions; Logger = loggerFactory.CreateLogger(new TLoggerCategory()); Options = loggingOptions; Interceptors = interceptors; }
/// <summary> /// From the <see cref="IInterceptors"/> object, returns the aggregator of interceptors of the given type. /// </summary> private InterceptorAggregator <TInterceptor> GetAggregator(IInterceptors interceptors) { var aggregator = ReflectionCache.GetAggregator(interceptors); return(aggregator); }
// Local function that creates and assigns the compiled getter static void SetAggregatorGetter(IInterceptors theInterceptors) { lock (Lock) { if (AggregatorGetter != null) { return; } try { // Check everything with slow reflection once var aggregatorsField = theInterceptors.GetType().GetField("_aggregators", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) ?? throw new Exception($"Field {theInterceptors.GetType().Name}._aggregators does not exist."); if (!typeof(IReadOnlyDictionary <Type, IInterceptorAggregator>).IsAssignableFrom(aggregatorsField.FieldType)) { throw new Exception($"Field {theInterceptors.GetType().Name}._aggregators is of unexpected type {aggregatorsField.FieldType.Name}."); } var aggregators = (IReadOnlyDictionary <Type, IInterceptorAggregator>?)aggregatorsField.GetValue(theInterceptors) ?? throw new Exception($"Field {theInterceptors.GetType().Name}._aggregators contains a null value."); if (!aggregators.TryGetValue(typeof(TInterceptor), out var aggregator)) { throw new Exception($"Field {theInterceptors.GetType().Name}._aggregators did not contain an aggregator for {typeof(TInterceptor).Name}."); } if (aggregator is null) { throw new Exception($"Field {theInterceptors.GetType().Name}._aggregators contained a null aggregator for {typeof(TInterceptor).Name}."); } if (aggregator is not InterceptorAggregator <TInterceptor> typedAggregator) { throw new Exception($"Field {theInterceptors.GetType().Name}._aggregators contained an aggregator for {typeof(TInterceptor).Name} of unexpected type {aggregator.GetType().Name}."); } // Compile a fast expression tree // Omit the checks, trusting that things will be the same in the future { var indexerMethod = typeof(IReadOnlyDictionary <Type, IInterceptorAggregator>).GetMethod("get_Item") ?? throw new Exception($"Type {typeof(IReadOnlyDictionary<Type, IInterceptorAggregator>).Name} does not have a single public indexer."); // IInterceptors interceptors; var param = Expression.Parameter(typeof(IInterceptors), "interceptors"); // (Interceptors)interceptors; var convertedParam = Expression.Convert(param, theInterceptors.GetType()); // ((Interceptors)interceptors)._aggregators; var aggregatorDictionary = Expression.Field(convertedParam, aggregatorsField); var interceptorType = Expression.Constant(typeof(TInterceptor)); // _aggregators[typeof(TInterceptor)] var interceptionAggregator = Expression.Call(aggregatorDictionary, indexerMethod, interceptorType); // (InterceptorAggregator<TInterceptor>)_aggregators[typeof(TInterceptor)] var convertedInterceptionAggregator = Expression.Convert(interceptionAggregator, typeof(InterceptorAggregator <TInterceptor>)); var lambda = Expression.Lambda <Func <IInterceptors, InterceptorAggregator <TInterceptor> > >(convertedInterceptionAggregator, param); AggregatorGetter = lambda.Compile(); } } catch (Exception e) { throw ThrowHelper.ThrowIncompatibleWithEfVersion(e); } } }