Skip to content

Allow combination of Specification with different projections #389

@gabrielheming

Description

@gabrielheming

Hello there,

I am using the Specification in a few projects that I am working on, and one of my projects came to the point that it has multiple Specifications only to represent different projections, using the same Where/Order expressions and/or Search Criteria.

This project in question is a WebAPI without any UI. At this moment, I am tweaking the current approach to map domain entities to their endpoints (VMs/DTOs). As some particular entities are loaded in different scenarios with partial data, we decided to map directly on the projection instead of loading the entity to memory and then mapping it to its VM/DTO.

My questioning came to the point that if I have to create a Specification per mapping/projection, is it still an advantage over the direct usage of DBContext? Of course, I am exaggerating it here, but it is only to make my point.

As Specification is easy to extend (extra points for you guys) I have created an extension method to combine a Specification with different projections.

My take on it is understanding whether it is useful/helpful or if it's just a load of BS making the purpose of Specification nonexistent.

In a nutshell, I created the IProjectionSpecification interface as below:

public interface IProjectionSpecification<T, TResult>
{
    public Expression<Func<T, TResult>>? Selector { get; }
    public void Select(Expression<Func<T, TResult>> selector);
}

And being able to use the extension method .ToProjection.

// VMs used as ex
public record StoreVm
{
    public int Id { get; set; }
    public string? Name { get; set; }
}

public record StoreWithStreetVm
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public string? Street { get; set; }
}

// Store and StoreByIdSpec are concrete classes from Ardalis.Specification.UnitTests
ISpecification<Store> storeByIdSpec = new StoreByIdSpec(1);
ISpecification<Store, StoreVm> mySpecWithProjection = storeByIdSpec.ToProjection(new MyStoreToStoreVm());
ISpecification<Store, StoreWithStreetVm> mySpecWithProjection2 = storeByIdSpec.ToProjection(new MyStoreToStoreWithStreetVm());

I don't think it's necessary to go into implementation details right now, but I'm interested in hearing your thoughts.

If you believe it would be useful, I can submit it as a pull request or create an extension package.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions