How to create dependency injection for ASP.NET MVC 5? - c#

Creating Dependency Injection with ASP.NET Core is fairly easy. The documentation explains it very well here and this guy has a killer video to explain it.
However, I want to do the same thing with my ASP.NET MVC 5 project. How can handle dependency injection with ASP.MVC 5?
Also, is Dependency injection limited to controllers only or can it work with any class?

In ASP.Net MVC you can use the .Net Core DI from NuGet rather than one of the third-party alternatives:-
using Microsoft.Extensions.DependencyInjection
For the MVC Start/Configuration class:-
public void Configuration(IAppBuilder app)
{
// We will use Dependency Injection for all controllers and other classes, so we'll need a service collection
var services = new ServiceCollection();
// configure all of the services required for DI
ConfigureServices(services);
// Configure authentication
ConfigureAuth(app);
// Create a new resolver from our own default implementation
var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());
// Set the application resolver to our default resolver. This comes from "System.Web.Mvc"
//Other services may be added elsewhere through time
DependencyResolver.SetResolver(resolver);
}
My project uses Identity User and I've replaced the OWIN start-up configuration to follow a service-based approach instead. The default Identity User classes use static factory methods to create instances. I've moved that code into the constructors and relied on DI to provide the appropriate injection. It is still work in progress but here is where I am at:-
public void ConfigureServices(IServiceCollection services)
{
//====================================================
// Create the DB context for the IDENTITY database
//====================================================
// Add a database context - this can be instantiated with no parameters
services.AddTransient(typeof(ApplicationDbContext));
//====================================================
// ApplicationUserManager
//====================================================
// instantiation requires the following instance of the Identity database
services.AddTransient(typeof(IUserStore<ApplicationUser>), p => new UserStore<ApplicationUser>(new ApplicationDbContext()));
// with the above defined, we can add the user manager class as a type
services.AddTransient(typeof(ApplicationUserManager));
//====================================================
// ApplicationSignInManager
//====================================================
// instantiation requires two parameters, [ApplicationUserManager] (defined above) and [IAuthenticationManager]
services.AddTransient(typeof(Microsoft.Owin.Security.IAuthenticationManager), p => new OwinContext().Authentication);
services.AddTransient(typeof(ApplicationSignInManager));
//====================================================
// ApplicationRoleManager
//====================================================
// Maps the rolemanager of identity role to the concrete role manager type
services.AddTransient<RoleManager<IdentityRole>, ApplicationRoleManager>();
// Maps the role store role to the implemented type
services.AddTransient<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>();
services.AddTransient(typeof(ApplicationRoleManager));
//====================================================
// Add all controllers as services
//====================================================
services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
.Where(t => typeof(IController).IsAssignableFrom(t)
|| t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
}
The Account Controller class has the single constructor:-
[Authorize]
public class AccountController : Controller
{
private ApplicationSignInManager _signInManager;
private ApplicationUserManager _userManager;
private RoleManager<IdentityRole> _roleManager;
public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, RoleManager<IdentityRole> roleManager)
{
UserManager = userManager;
SignInManager = signInManager;
RoleManager = roleManager;
}
}
My Default Dependency Resolver:
/// <summary>
/// Provides the default dependency resolver for the application - based on IDependencyResolver, which hhas just two methods
/// </summary>
public class DefaultDependencyResolver : IDependencyResolver
{
/// <summary>
/// Provides the service that holds the services
/// </summary>
protected IServiceProvider serviceProvider;
/// <summary>
/// Create the service resolver using the service provided (Direct Injection pattern)
/// </summary>
/// <param name="serviceProvider"></param>
public DefaultDependencyResolver(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
/// <summary>
/// Get a service by type - assume you get the first one encountered
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public object GetService(Type serviceType)
{
return this.serviceProvider.GetService(serviceType);
}
/// <summary>
/// Get all services of a type
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public IEnumerable<object> GetServices(Type serviceType)
{
return this.serviceProvider.GetServices(serviceType);
}
}

For this answer I downloaded a Microsoft Example of WebApi project as a basis for the example and added DI services to it as follows,
Update the Target Framework to 4.6.1
NuGet the DI package :- Microsoft.Extensions.DependencyInjection
After the standard MapHttpRoute configuration, add code to register which services you need
using's
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using Microsoft.Extensions.DependencyInjection;
using System.Web.Http.Dependencies;
using ProductsApp.Controllers;
WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// create the DI services and make the default resolver
var services = new ServiceCollection();
services.AddTransient(typeof(DefaultProduct));
services.AddTransient(typeof(ProductsController));
var resolver = new MyDependencyResolver(services.BuildServiceProvider());
config.DependencyResolver = resolver;
}
}
DefaultProduct
public class DefaultProduct : ProductsApp.Models.Product
{
public DefaultProduct()
{
this.Category = "Computing";
this.Id = 999;
this.Name = "Direct Injection";
this.Price = 99.99M;
}
}
MyDependencyResolver
/// <summary>
/// Provides the default dependency resolver for the application - based on IDependencyResolver, which hhas just two methods.
/// This is combined dependency resolver for MVC and WebAPI usage.
/// </summary>
public class MyDependencyResolver : System.Web.Mvc.IDependencyResolver, System.Web.Http.Dependencies.IDependencyResolver
{
protected IServiceProvider serviceProvider;
protected IServiceScope scope = null;
public MyDependencyResolver(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public MyDependencyResolver(IServiceScope scope)
{
this.scope = scope;
this.serviceProvider = scope.ServiceProvider;
}
public IDependencyScope BeginScope()
{
return new MyDependencyResolver(serviceProvider.CreateScope());
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
scope?.Dispose();
}
public object GetService(Type serviceType)
{
return this.serviceProvider.GetService(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return this.serviceProvider.GetServices(serviceType);
}
}
ServiceProviderExtensions
public static class ServiceProviderExtensions
{
public static IServiceCollection AddControllersAsServices(this IServiceCollection services, IEnumerable<Type> serviceTypes)
{
foreach (var type in serviceTypes)
{
services.AddTransient(type);
}
return services;
}
}
I then amended the existing controller to take the DI type (note there is just the one ctor)
using ProductsApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace ProductsApp.Controllers
{
public class ProductsController : ApiController
{
DefaultProduct _dp = null;
public ProductsController(DefaultProduct dp)
{
_dp = dp;
//
products.Add(dp);
}
List<Product> products = new List<Product>()
{
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
};
public IEnumerable<Product> GetAllProducts()
{
return products;
}
public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
}
}

My Default Dependency Resolver
/// <summary>
/// Provides the default dependency resolver for the application - based on IDependencyResolver, which hhas just two methods
/// </summary>
public class DefaultDependencyResolver : IDependencyResolver
{
/// <summary>
/// Provides the service that holds the services
/// </summary>
protected IServiceProvider serviceProvider;
/// <summary>
/// Create the service resolver using the service provided (Direct Injection pattern)
/// </summary>
/// <param name="serviceProvider"></param>
public DefaultDependencyResolver(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
/// <summary>
/// Get a service by type - assume you get the first one encountered
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public object GetService(Type serviceType)
{
return this.serviceProvider.GetService(serviceType);
}
/// <summary>
/// Get all services of a type
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public IEnumerable<object> GetServices(Type serviceType)
{
return this.serviceProvider.GetServices(serviceType);
}
}

I recommend you use Autofac, there are anothers fwk like unity, ninject, the benchmarks autofac has excelent perfomance.
http://www.palmmedia.de/blog/2011/8/30/ioc-container-benchmark-performance-comparison
Here is the integration with MVC (and works with all class)
http://docs.autofac.org/en/latest/integration/mvc.html

The simplest way to implements Dependency Injection in ASP.NET MVC 5 is to use the tool developed by Microsoft itself, called Unity.
You can find many resources on the internet about it, and you can start by reading the official documentation available here: Developer's Guide to Dependency Injection Using Unity
Also, is Dependency injection limited to controllers only or can it work with any class?
It works with any class, in any project, as long as you register the Interface related to the Implementation (if you want to take profit of the IoC pattern), all you have to do then is to add the Interface instantiation in your constructor.

In this video a Microsoft MVP demos dependency injection in MVC5 with AutoFac. Very clear explanation on how to set it up:
Dependency Injection MVC5 Demo
Source code is available on GitHub

From here https://scottdorman.blog/2016/03/17/integrating-asp-net-core-dependency-injection-in-mvc-4/
this line saved me.
services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
.Where(t => typeof(IController).IsAssignableFrom(t)
|| t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));

I recommend using Windsor, by installing the nuget package Castle Windsor MVC Bootstrapper, then you can create a service that implements IWindsorInstaller, something like this:
public class ServiceRegister : IWindsorInstaller
{
public void Install(Castle.Windsor.IWindsorContainer container,
Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
SomeTypeRequiredByConstructor context = new SomeTypeRequiredByConstructor ();
container.Register(
Component
.For<IServiceToRegister>()
.ImplementedBy<ServiceToRegister>().
DependsOn(Dependency.OnValue<SomeTypeRequiredByConstructor>(context))//This is in case your service has parametrize constructoe
.LifestyleTransient());
}
}
Then inside your controller something like this:
public class MyController
{
IServiceToRegister _serviceToRegister;
public MyController (IServiceToRegister serviceToRegister)
{
_serviceToRegister = serviceToRegister;//Then you can use it inside your controller
}
}
And by default the library will handle sending the right service to your controller by calling the install() of ServiceRegister at start up because it implements IWindsorInstaller

Having started from this thread to figure out how to use Microsoft.Extensions.DependencyInjection in my ASP.NET MVC 5 project, and reading and trying and failing, I finally came up with a solution that I wanted to shamelessly offer to the rest of you.
I pieced together a gist from David Fowler, the example code from Scott Dorman, and added in a bit of my own spice to create library that allows you to simulate ASP.NET Core's Startup in ASP.NET MVC "Classic".
For more information, please take a look at the GitHub repository for Arex388.AspNet.Mvc.Startup. If you're interested you can also read through my blog post about it, here (if it doesn't load, refresh until it does, the server's been giving me troubles and I haven't had time to investigate...). Hope it helps someone!

Related

How to share ServiceProvider in Maui Blazor for Maui services and Blazor services

I am trying to figure out how to share the services between Maui and Blazor in a MauiBlazor project.
The goal is to be able to consume the same singletons without having a static instance of these singletons stored somewhere.
While it may be a more convenient way in the future releases, I found a way to do that with some inspirations from Maui.Plugins.PageResolver. Related to the issue maui#792
I have added a nuget + working sample app on Github
Here is how I solved it:
1. Create a repository for the service provider
public static class Resolver
{
private static IServiceProvider _serviceProvider;
public static IServiceProvider ServiceProvider => _serviceProvider ?? throw new Exception("Service provider has not been initialized");
/// <summary>
/// Register the service provider
/// </summary>
public static void RegisterServiceProvider(IServiceProvider sp)
{
_serviceProvider = sp;
}
/// <summary>
/// Get service of type <typeparamref name="T"/> from the service provider.
/// </summary>
public static T Resolve<T>() where T : class
=> ServiceProvider.GetRequiredService<T>();
}
2. An extension method for the app startup
public static void UseResolver(this MauiApp app)
{
Resolver.RegisterServiceProvider(app.Services);
}
Or to avoid dependency to Maui:
public static void UseResolver(this IServiceProvider sp)
{
Resolver.RegisterServiceProvider(sp);
}
3a. A sample test service
public class TestSingletonService
{
private static int _staticIndex = 0;
public int Index { get; set; }
public TestSingletonService()
{
Index = _staticIndex++;
}
}
3b. Register the service collection
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.RegisterBlazorMauiWebView()
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
builder.Services.AddBlazorWebView();
builder.Services.AddSingleton<WeatherForecastService>();
// Register any other service / ViewModel / Page here
builder.Services.AddSingleton<TestSingletonService>();
// Pre-build the app
var app = builder.Build();
// Intercept and register the ServiceProvider
app.UseResolver();
// Or to avoid Maui dependency
// app.Services.UseResolver();
// Return the app as usual
return app;
}
}
4a. Use it as your factory from Maui side
Resolver.ServiceProvider.GetRequiredService<TestSingletonService>();
Console.WriteLine($"Instance number {TestSingletonService.Index}");
4b. The services instances will be shared with your Blazor #inject services.
#inject TestSingletonService tester
Instance number #(tester.Index).

Pass Parameters to AddHostedService

I am writing a .Net Core windows service and here is a snippet of code:
internal static class Program
{
public static async Task Main(string[] args)
{
var isService = !(Debugger.IsAttached || args.Contains("--console"));
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<IntegrationService>();
});
if (isService)
{
await builder.RunAsServiceAsync();
}
else
{
await builder.RunConsoleAsync();
}
}
}
I want to pass some parameters to my service i.e. IntegrationService - how I can send parameters to my service?
Small update on Joelius answer for .Net Core 3
Given an HostedService with this constructor mixing parameters (TimeSpan) and services (ILogger<StatusService>, IHttpClientFactory)
public StatusService(
TimeSpan cachePeriod,
ILogger<StatusService> logger,
IHttpClientFactory clientFactory)
You can in your Startup.cs add it to your HostedService like this :
services.AddHostedService
(serviceProvider =>
new StatusService(
TimeSpan.FromDays(1),
serviceProvider.GetService<ILogger<StatusService>>(),
serviceProvider.GetService<IHttpClientFactory>()));
While the answers above are correct, they do have the downside that you can't use DI in the Services Constructor anymore.
What I did instead was:
class Settings {
public string Url { get; set; }
}
class SomeService : IHostedService {
public SomeService (string instanceId, IOptionsMonitor<Settings> optionsMonitor) {
var settings = optionsMonitor.Get(instanceId);
}
}
services.Configure<Settings>("Instance1", (s) => s.Url = "http://google.com");
services.Configure<Settings>("Instance2", (s) => s.Url = "http://facebook.com");
services.AddSingleton<IHostedService>(x =>
ActivatorUtilities.CreateInstance<SomeService>(x, "Instance1")
);
services.AddSingleton<IHostedService>(x =>
ActivatorUtilities.CreateInstance<SomeService>(x, "Instance2")
);
This creates named settings for each instance and passes the named settings name to the HostedService.
If you want multiple Services with the same Class and different parameters make sure to use AddSingleton instead of AddHostedService as AddHostedService will add only one instance of the same Type which will result in only one instance being started!
What Joelius answered is correct although there is another way of doing this
services.AddSingleton<IHostedService>(provider => new IntegrationService("Test"));
Before .net core 3 you can use a config class which you can inject into the service via DI.
Your config class could look like this:
class IntegrationConfig
{
public int Timeout { get; set; }
public string Name { get; set; }
}
Then you need to add this config to the DI-system:
services.AddSingleton(new IntegrationConfig
{
Timeout = 1234,
Name = "Integration name"
});
In the class IntegrationService you need to add a constructor which takes an object of the config:
public IntegrationService(IntegrationConfig config)
{
// setup with config or simply store config
}
That's basically all you need. It's not the prettiest solution in my opinion and in .net core 3
you can simply use a factory func to add the HostedService but I think something like this is the best choice
if you're on .net core 2.2 or below.
EDIT:
In the comments Kirk Larkin mentions this:
You can emulate the overload. It's just a wrapper around AddTransient(), which of course does support the factory func approach.
For this you might want to look at the current overload which is accessable here:
/// <summary>
/// Add an <see cref="IHostedService"/> registration for the given type.
/// </summary>
/// <typeparam name="THostedService">An <see cref="IHostedService"/> to register.</typeparam>
/// <param name="services">The <see cref="IServiceCollection"/> to register with.</param>
/// <param name="implementationFactory">A factory to create new instances of the service implementation.</param>
/// <returns>The original <see cref="IServiceCollection"/>.</returns>
public static IServiceCollection AddHostedService<THostedService>(this IServiceCollection services, Func<IServiceProvider, THostedService> implementationFactory)
where THostedService : class, IHostedService
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService>(implementationFactory));
return services;
}
Note that the last commit that changed this file was on June 3rd and is tagged for preview6 and preview7 of .net core 3. Because I've never heard of TryAddEnumerable and am no microsoft employee, I don't know if you can directly translate that.
Just from looking at the current implementation of AddTransient and going down the rabbit hole a few files more, I sadly can't draw the lines well enough to be able to give you the exact functionality you're currently able to get with .net core 3.
The workaround I gave still works and seems acceptable depending on the situation.

Is it possible to instantiate a class which contains an injected enum

Is it possible using Microsoft's DI to inject an enum?
I am getting the following exception when instantiating a class which contains a enum in the constructor.
InvalidOperationException:
Unable to resolve service for type DependencyInjectionWithEnum.Domain.Types.TestType
while attempting to activate DependencyInjectionWithEnum.Domain.Service.TestService
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)
I have the following enum:
/// <summary>
/// This is a test enum which is injected into the TestService's constructor
/// </summary>
public enum TestType
{
First,
Second,
Third,
Forth,
Fifth
}
Which gets injected into the following
public class TestService
{
private readonly TestType testType;
/// <summary>
/// Here I am injecting an enum called TestType
/// </summary>
/// <param name="testType"></param>
public TestService(TestType testType)
{
this.testType = testType;
}
/// <summary>
/// This is a dummy method.
/// </summary>
/// <returns></returns>
public string RunTest()
{
switch(testType.ToString().ToUpperInvariant())
{
case "First":
return "FIRST";
case "Second":
return "SECOND";
case "Third":
return "THIRD";
case "Forth":
return "FORTH";
case "Fifth":
return "FIFTH";
default:
throw new InvalidOperationException();
}
}
}
Then in Startup.cs I add the TestService to the ServiceCollection
public void ConfigureServices(IServiceCollection services)
{
//mvc service
services.AddMvc();
// Setup the DI for the TestService
services.AddTransient(typeof(TestService), typeof(TestService));
//data mapper profiler setting
Mapper.Initialize((config) =>
{
config.AddProfile<MappingProfile>();
});
//Swagger API documentation
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "DependencyInjectionWithEnum
API", Version = "v1" });
});
}
Finally I inject my TestService into my controller
[Route("api/[controller]")]
public class TestController : ControllerBase
{
private readonly TestService testService;
/// <summary>
/// Here I am injecting a TestService. The TestService is the class from which I am attempting to inject an enum
/// </summary>
/// <param name="testService"></param>
public TestController(TestService testService)
{
this.testService = testService;
}
/// <summary>
/// Dummy get
/// </summary>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(200, Type = typeof(string))]
public IActionResult Get()
{
var testResult = testService.RunTest();
return Ok(testResult);
}
}
I get the exception when attempting to call the controller's endpoint via Swagger.
Tech Stack
- Visual Studio v15.9.4 C# v7.3
- Project Target Framework .NET Core 2.2
- NuGet Packages
- Microsoft.AspNetCore v2.2.0
- Microsoft.AspNetCore.Mvc v2.2.0
- Microsoft.Extensions.DependencyInjection v2.2.0
Is it possible using Microsoft's DI to inject an enum?
YES
Out of the box the enum can be added with a factory delegate when registering the service at start up
// Setup the DI for the TestService
services.AddTransient<TestService>(sp => new TestService(TestType.First));
When injecting TestService into any dependents the container will use the factory delegate to resolve the class and its dependencies.

Microsoft Unity Service is null when controller is hit

I'm looking at Microsoft Unity injection for a webapi we've based on the full stack code i found here;
Full Stack WebApi GitHub Repo
Now when I run the code and hit the patients controller in this case, the
[Dependency]
public PatientService PatientService { get; set; }
is null.
Now the patient service is the entity having the context injected into its constructor.
public class PatientService : BaseService
{
private readonly Func<IUCareDataContext> _contextFactory;
/// <summary>
/// Initializes a new instance of the <see cref="PatientService"/> class.
/// </summary>
/// <param name="contextFactory">The context factory.</param>
public PatientService(Func<IUCareDataContext> contextFactory)
{
this._contextFactory = contextFactory;
}
From looking at the Unity documentation and UnityConfig.cs I can see that the Register is completed, but no Resolve?
namespace CCS.Services.WebApi
{
using CCS.Data.UCare;
using Data;
using Microsoft.Practices.Unity;
using System.Web.Http;
using Unity.WebApi;
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IUCareDataContext, UCareDataContext>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
}
Unity [Dependency] Attribute MSDN
Is this implementation missing something or should the dependency injection just work automatically when the controller is instantiated?
As it was pointed out I could inject the service. But this would then mean I would have to register every service to unity, with all services ultimately having the same context interface being injected to it. I would have thought there is a way around this?

How do I instiate a class with it's dependencies using Ninject

In my MVC application I have a concept of "scheduled job".
A job inherits from an interface and is then (via reflection) automatically registered on application start.
Now, in my application I am using Ninject for DI to help make my controllers more unit testable. I would love to use ninject for my Scheduled Jobs too but am currently using "poor man's DI" to instantiate my Job's with their dependencies.
So, how exactly would I use Ninject instead of Poor Man's DI?
Job Interface:
public interface IScheduledJob
{
/// <summary>
/// Use Cron method to return frequency expression
/// </summary>
string Frequency { get; }
/// <summary>
/// The entry point of the Job
/// </summary>
void DoWork();
}
Job Init Code:
private void ConfigureSchedules(IAppBuilder app)
{
// Get all types that implement the scheduler interface
IEnumerable<Type> jobs = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => typeof(IScheduledJob).IsAssignableFrom(p) && !p.IsInterface);
foreach (var jobType in jobs)
{
// Create instance of job
IScheduledJob job = (IScheduledJob)Activator.CreateInstance(jobType);
// Add to schedule
RecurringJob.AddOrUpdate(() => job.DoWork(), job.Frequency);
}
}
Scheduled Job Ctors:
public class SynchronizerScheduledJob : IScheduledJob
{
#region Private Members
private IMagentoSoapService _magentoSoapService;
private IMagentoSoapCredentialProvider _credsProvider;
private IUnitOfWork _unitOfWork;
private IOrderHubService _orderHubService;
#endregion
#region Ctors
public SynchronizerScheduledJob(
IMagentoSoapService service,
IMagentoSoapCredentialProvider credsProvider,
IUnitOfWork unitOfWork,
IOrderHubService orderHubService)
{
_magentoSoapService = service;
_credsProvider = credsProvider;
_unitOfWork = unitOfWork;
_orderHubService = orderHubService;
}
/// <summary>
/// Poor man's DI Ctor
/// </summary>
public SynchronizerScheduledJob() : this(
new MagentoSoapService(),
new MagentoSoapCredentialProvider(),
new UnitOfWork(AppDbContext.Create()),
new OrderHubService())
{ }
}

Categories

Resources