jonwagner / Insight.Database

Fast, lightweight .NET micro-ORM
Other
861 stars 145 forks source link

Can abstract auto interface take dependency? #400

Closed ThisNoName closed 5 years ago

ThisNoName commented 5 years ago

Some common queries are always cached, so having something like this could save quite a bit of hassle else where.

public abstract partial class MyQuery  {
    public ICacheService CacheService;

    public PortalQuery(ICacheService cacheService) => CacheService = cacheService;

    public IEnumerable<string> IdbInsurance(string mrn) {
        return CacheService.Get("somelist", () => GetConnection().Query<string>("SELECT"));
} 

I couldn't figure out if this is possible since auto interface IoC seems expecting default constructor with no parameters.

services.AddScoped(x => 
    new SqlConnectionStringBuilder(conn).As<MyQuery>());

Any suggestions? Thanks.

jonwagner commented 5 years ago

Right. the .As<X> auto-implementation only expects to pass a connection to the constructor.

I can think of 2 ways to approach it.

  1. Use property injection to insert the cache service
services.AddScoped(x => {
     var myQuery = new SqlConnectionStringBuilder(conn).As<MyQuery>();
     myQuery.cacheService = context.Get<ICacheService>();
     return myQuery;
})
  1. Use a layered approach to separate the concerns. You would have to write each of the methods (meh), or this one might be possible with a separate proxy layer or maybe there is a caching library that does all of the wiring up for you. (If not, there should be)
class MyQuery : IQuery {
    constructor (ICacheService, IQuery inner) { /* inject both */ }
    public foo TheQuery(params) {
        return CacheService.get(x, () => inner.TheQuery(params));
    }
}
ThisNoName commented 5 years ago

Thanks. I'll take injection. Layered approach is apparently more elegant, but this whole thing is out of pure laziness pampered by auto interface ^_^

jonwagner commented 5 years ago

hahaha :)

I would look for a caching layer that does proxying. if there isn't one, someone should write it.

I would love to do:

interface CachedQueries : IQuery {
   // leave most definitions alone

   [CachePolicy (blah)]
   // repeat method signature
}

or even something that would cache with an external policy:

    var iquery = conn.As<IQuery>();
    var cached = CachePolicy.Wrap(iquery)
ThisNoName commented 5 years ago

Thanks. I usually handle memory cache and db cache (for remote db) similarly, using attribute or injecting caching service via constructor. This particular one is only reserved for a handful of frequently used and always cached calls.