Skip to content

Add support for additional arbitrary specification state. #247

@fiseni

Description

@fiseni

We designed the infrastructure to be as extensible as possible. For example, users can define their own builder extensions, can define and inject their evaluators, validators and so on. But, all this is true as long you're working with the existing specification state. If you need to keep an additional information in the specification, then you have no other choice then define your own specification type (it may or may not inherit from the provided one in the library). This process can be tedious and it's not a simple task.

A common solution in these scenarios is just to define a IDictionary<string, object> that can hold an arbitrary state. Users will be able to extend the state by adding it in the dictionary. Let's provide an example usage. Let's say we want to add support for "AsSingleQuery".

You define an extension to the builder:

namespace Ardalis.Specification;

public static class SpecificationExtensions
{
  public static ISpecificationBuilder<T> AsSingleQuery<T>(
      this ISpecificationBuilder<T> specificationBuilder,
      bool condition = true) where T : class
  {
    if (condition)
    {
      specificationBuilder.Specification.Items["AsSingleQuery"] = true;
    }

    return specificationBuilder;
  }
}

You define the evaluator:

using Microsoft.EntityFrameworkCore;

namespace Ardalis.Specification.EntityFrameworkCore;

public class AsSingleQueryEvaluator : IEvaluator
{
  private AsSingleQueryEvaluator() { }
  public static AsSingleQueryEvaluator Instance { get; } = new AsSingleQueryEvaluator();

  public bool IsCriteriaEvaluator { get; } = true;

  public IQueryable<T> GetQuery<T>(IQueryable<T> query, ISpecification<T> specification) where T : class
  {
    if (specification.Items.TryGetValue("AsSingleQuery", out var value) && (bool)value)
    {
      query = query.AsSingleQuery();
    }

    return query;
  }
}

As seen above, this can greatly improve the extensibility of the specifications.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions