Skip to content

Commit

Permalink
Make EvaluableExpressionFilter public
Browse files Browse the repository at this point in the history
  • Loading branch information
roji committed Jul 26, 2019
1 parent a02785c commit 0d69d40
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ public override EntityFrameworkServicesBuilder TryAddCoreServices()
.AddDependencyScoped<HistoryRepositoryDependencies>()
.AddDependencyScoped<RelationalCompiledQueryCacheKeyGeneratorDependencies>()
.AddDependencyScoped<RelationalConnectionDependencies>()
.AddDependencyScoped<RelationalDatabaseDependencies>();
.AddDependencyScoped<RelationalDatabaseDependencies>()
.AddDependencyScoped<RelationalEvaluatableExpressionFilterDependencies>();

return base.TryAddCoreServices();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Linq.Expressions;
Expand All @@ -7,7 +7,7 @@
using Microsoft.EntityFrameworkCore.Utilities;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.EntityFrameworkCore.Query.Internal
namespace Microsoft.EntityFrameworkCore.Query
{
/// <summary>
/// <para>
Expand All @@ -33,13 +33,22 @@ public class RelationalEvaluatableExpressionFilter : EvaluatableExpressionFilter
/// 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 RelationalEvaluatableExpressionFilter([NotNull] IModel model)
public RelationalEvaluatableExpressionFilter(
[NotNull] EvaluatableExpressionFilterDependencies dependencies,
[NotNull] RelationalEvaluatableExpressionFilterDependencies relationalDependencies)
: base(dependencies)
{
Check.NotNull(model, nameof(model));
Check.NotNull(relationalDependencies, nameof(relationalDependencies));

_model = model;
RelationalDependencies = relationalDependencies;
_model = relationalDependencies.Model;
}

/// <summary>
/// Dependencies used to create a <see cref="RelationalEvaluatableExpressionFilter" />
/// </summary>
protected virtual RelationalEvaluatableExpressionFilterDependencies RelationalDependencies { get; }

/// <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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Utilities;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.EntityFrameworkCore.Query
{
/// <summary>
/// <para>
/// Service dependencies parameter class for <see cref="RelationalEvaluatableExpressionFilter" />
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// <para>
/// Do not construct instances of this class directly from either provider or application code as the
/// constructor signature may change as new dependencies are added. Instead, use this type in
/// your constructor so that an instance will be created and injected automatically by the
/// dependency injection container. To create an instance with some dependent services replaced,
/// first resolve the object from the dependency injection container, then replace selected
/// services using the 'With...' methods. Do not call the constructor at any point in this process.
/// </para>
/// <para>
/// The service lifetime is <see cref="ServiceLifetime.Scoped"/>. This means that each
/// <see cref="DbContext"/> instance will use its own instance of this service.
/// The implementation may depend on other services registered with any lifetime.
/// The implementation does not need to be thread-safe.
/// </para>
/// </summary>
public sealed class RelationalEvaluatableExpressionFilterDependencies
{
/// <summary>
/// <para>
/// Creates the service dependencies parameter object for a <see cref="RelationalEvaluatableExpressionFilter" />.
/// </para>
/// <para>
/// Do not call this constructor directly from either provider or application code as it may change
/// as new dependencies are added. Instead, use this type in your constructor so that an instance
/// will be created and injected automatically by the dependency injection container. To create
/// an instance with some dependent services replaced, first resolve the object from the dependency
/// injection container, then replace selected services using the 'With...' methods. Do not call
/// the constructor at any point in this process.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
[EntityFrameworkInternal]
public RelationalEvaluatableExpressionFilterDependencies([NotNull] IModel model)
{
Check.NotNull(model, nameof(model));

Model = model;
}

/// <summary>
/// The model used with this <see cref="RelationalEvaluatableExpressionFilter"/>.
/// </summary>
public IModel Model { get; }

/// <summary>
/// Clones this dependency parameter object with one service replaced.
/// </summary>
/// <param name="model"> A replacement for the current dependency of this type. </param>
/// <returns> A new parameter object with the given service replaced. </returns>
public RelationalEvaluatableExpressionFilterDependencies With([NotNull] IModel model)
=> new RelationalEvaluatableExpressionFilterDependencies(model);
}
}
3 changes: 2 additions & 1 deletion src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ public virtual EntityFrameworkServicesBuilder TryAddCoreServices()
.AddDependencyScoped<CompiledQueryCacheKeyGeneratorDependencies>()
.AddDependencyScoped<QueryContextDependencies>()
.AddDependencyScoped<ValueGeneratorSelectorDependencies>()
.AddDependencyScoped<DatabaseDependencies>();
.AddDependencyScoped<DatabaseDependencies>()
.AddDependencyScoped<EvaluatableExpressionFilterDependencies>();

ServiceCollectionMap.TryAddSingleton<IRegisteredServices>(
new RegisteredServices(ServiceCollectionMap.ServiceCollection.Select(s => s.ServiceType)));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Linq.Expressions;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Utilities;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.EntityFrameworkCore.Query.Internal
namespace Microsoft.EntityFrameworkCore.Query
{
/// <summary>
/// <para>
Expand All @@ -22,7 +25,7 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal
/// The implementation does not need to be thread-safe.
/// </para>
/// </summary>
public class EvaluatableExpressionFilter : EvaluatableExpressionFilterBase
public class EvaluatableExpressionFilter : IEvaluatableExpressionFilter
{
// This methods are non-deterministic and result varies based on time of running the query.
// Hence we don't evaluate them. See issue#2069
Expand Down Expand Up @@ -54,13 +57,36 @@ private static readonly MethodInfo _randomNextOneArg
private static readonly MethodInfo _randomNextTwoArgs
= typeof(Random).GetRuntimeMethod(nameof(Random.Next), new[] { typeof(int), typeof(int) });

/// <summary>
/// Parameter object containing dependencies for this service.
/// </summary>
protected virtual EvaluatableExpressionFilterDependencies Dependencies { get; }

/// <summary>
/// <para>
/// Creates a new <see cref="EvaluatableExpressionFilter"/> instance.
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// </summary>
/// <param name="dependencies"> The dependencies to use. </param>
public EvaluatableExpressionFilter(
[NotNull] EvaluatableExpressionFilterDependencies dependencies)
{
Check.NotNull(dependencies, nameof(dependencies));

Dependencies = dependencies;
}

/// <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 override bool IsEvaluatableExpression(Expression expression)
public virtual bool IsEvaluatableExpression(Expression expression)
{
switch (expression)
{
Expand Down Expand Up @@ -91,7 +117,7 @@ public override bool IsEvaluatableExpression(Expression expression)
break;
}

return base.IsEvaluatableExpression(expression);
return true;
}
}
}
58 changes: 58 additions & 0 deletions src/EFCore/Query/EvaluatableExpressionFilterDependencies.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.EntityFrameworkCore.Query
{
/// <summary>
/// <para>
/// Service dependencies parameter class for <see cref="EvaluatableExpressionFilter" />
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// <para>
/// Do not construct instances of this class directly from either provider or application code as the
/// constructor signature may change as new dependencies are added. Instead, use this type in
/// your constructor so that an instance will be created and injected automatically by the
/// dependency injection container. To create an instance with some dependent services replaced,
/// first resolve the object from the dependency injection container, then replace selected
/// services using the 'With...' methods. Do not call the constructor at any point in this process.
/// </para>
/// <para>
/// The service lifetime is <see cref="ServiceLifetime.Scoped"/>. This means that each
/// <see cref="DbContext"/> instance will use its own instance of this service.
/// The implementation may depend on other services registered with any lifetime.
/// The implementation does not need to be thread-safe.
/// </para>
/// </summary>
public sealed class EvaluatableExpressionFilterDependencies
{
/// <summary>
/// <para>
/// Creates the service dependencies parameter object for a <see cref="EvaluatableExpressionFilter" />.
/// </para>
/// <para>
/// Do not call this constructor directly from either provider or application code as it may change
/// as new dependencies are added. Instead, use this type in your constructor so that an instance
/// will be created and injected automatically by the dependency injection container. To create
/// an instance with some dependent services replaced, first resolve the object from the dependency
/// injection container, then replace selected services using the 'With...' methods. Do not call
/// the constructor at any point in this process.
/// </para>
/// <para>
/// 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.
/// </para>
/// </summary>
[EntityFrameworkInternal]
public EvaluatableExpressionFilterDependencies()
{
}
}
}
33 changes: 0 additions & 33 deletions src/EFCore/Query/Internal/EvaluatableExpressionFilterBase.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit;

namespace Microsoft.EntityFrameworkCore.Query
{
public class RelationalEvaluatableExpressionFilterDependenciesTest
{
[ConditionalFact]
public void Can_use_With_methods_to_clone_and_replace_service()
{
RelationalTestHelpers.Instance.TestDependenciesClone<RelationalEvaluatableExpressionFilterDependencies>();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit;

namespace Microsoft.EntityFrameworkCore.Query
{
public class EvaluatableExpressionFilterDependenciesTest
{
[ConditionalFact]
public void Can_use_With_methods_to_clone_and_replace_service()
{
InMemoryTestHelpers.Instance.TestDependenciesClone<EvaluatableExpressionFilterDependencies>();
}
}
}

0 comments on commit 0d69d40

Please sign in to comment.