Search code examples
c#.net-core

How to execute the method passed as an Expression<Action<T>> argument?


I have a class in a .netcore aplication which is used to enqueu background tasks:

public interface IBackgroundTasksService {
  void RunBackgroundTask<T>(Expression<Action<T>> methodCall);
}

public class BackgroundTasksService : IBackgroundTasksService {
  public void RunBackgroundTask<T>(Expression<Action<T>> methodCall){
   // calls to the Backgorund service worker thrid party library with `methodCall` as a param.
   // this works as expected
  }
}

When called by other services, this is the usual pattern:

_backgroundTasksService.RunBackgroundTask<MyService>(x => x.Execute(id, name, color));

This is the issue: When running Unit tests I need the methodCall to be called instead of having it logged for the backgound worker, so I created a stub for the BackgroundTasksService:

public class BackgroundTasksServiceStub : IBackgroundTasksService {
  public void RunBackgroundTask<T>(Expression<Action<T>> methodCall){
    Expression.Lambda(methodCall).Compile().DynamicInvoke(); // this is just one of the attempts (it does not work)

  }
}

I have tried a few different approaches, but I am yet to see one that makes the call to MyService.Execute ...

What would be an approach for executing the argument method?


Solution

  • Thanks to the comments from the question I got it to work!

    This is how the working stub class goes:

    public class BackgroundTasksServiceStub : IBackgroundTasksService {
      private readonly IServiceProvider _serviceProvider;
    
      public BackgroundTasksServiceStub(IServiceProvider serviceProvider){
        _serviceProvider = serviceProvider;
      }
    
      public void RunBackgroundTask<T>(Expression<Action<T>> methodCall){
        var service = _serviceProvider.GetService<T>();
        var method = methodCall.Compile();
        method(service);
      }
    }