ClaveConsulting / Expressionify

Use extension methods in Entity Framework Core queries
MIT License
172 stars 12 forks source link

Support for Conventions #6

Open mpetito opened 4 years ago

mpetito commented 4 years ago

It would be nice if this library could be applied to a project by convention so that there are fewer explicit references of Expressionify throughout the code. I'm interested in using this library to map from entities to DTOs explicitly. Some thoughts to make this work by convention:

  1. Register an IMethodCallTranslator with EF that handles the same logic as ExpressionifyVisitor. This would eliminate the need to use Expressionify() extension method on IQueryable. See also this example.

  2. Support assembly-level attributes that indicate a namespace- or method-name pattern for convention-based method inclusion.

I think the outcome should be something as simple as:

// configure entity-framework
services.AddDbContext<DbContextType>(options => options
  .UseSqlServer(...)
  .AddExpressionify()
);
// apply convention to all suitable methods in an entire namespace
[assembly: ExpressionifyConvention(Namespace="Project.Mappings")]

// or apply convention to all matching method names by pattern in a namespace
[assembly: ExpressionifyConvention(Namespace="Project.Models", MethodPattern="MapFrom.*")]
mariusGundersen commented 4 years ago

The first suggestion should be pretty simple to implement, a pull request is greatly appreciated.

The second part is a bit more difficult, and maybe not such a good idea. I think, because of how this works, it might be better to have it as a property in the csproj file. This is because the way the translation is done now is that each file is scanned and processed individually and in the order decided by msbuild, so it's not certain an assembly attribute in one file is discovered before a potential expression method is discovered in another file. But with an msbuild property the pattern is known before any file is scanned.

But I'm not sure how to best report that a file was not processed because it didn't match a pattern. This is a general problem with conventions, where there is no indication to me as a developer why one method was expressionified while another one was not. There is also the question of should it be an error to have a method that matches the pattern but isn't static or doesn't have an expression body? Or should it silently be ignored? That is, should we worry more about false positives or false negatives?