-
Notifications
You must be signed in to change notification settings - Fork 251
Description
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.