I'm trying to do a bit of a balancing act here. Currently Azure WebJobs don't support .NET Core.
With some help, I created a .NET Core Console App and made it work as a WebJob. On top of that I'm trying to implement Ninject for DI.
Code compiles fine but when I run it, I'm getting the "No parameterless constructor is defined for this object." error -- see below.
I may be in a bit of unchartered territory here with Azure WebJobs, .NET Core 2.0 and Ninject but any idea what may be causing this?
BTW, I had the same exact code running as a WebJob targeting .NET Framework. I needed to migrate to .NET Core 2.0 because I'm using class libraries that target .NET Core 2.0. I'm also using DI in those class libraries which is why I'm trying to migrate my WebJob to .NET Core 2.0 using Ninject.
P.S. I'm using Azure.WebJobs 3.0.0 beta2 to convert my .NET Core console app to WebJobs. I'm also using Ninject 3.2.2
UPDATE: Here's my code for the JobActivator
public class BrmJobActivator : IJobActivator
{
private readonly IKernel _container;
public BrmJobActivator(IKernel container)
{
_container = container;
}
public T CreateInstance<T>()
{
return _container.Get<T>();
}
}
And here's the main Program:
class Program
{
static readonly IKernel Kernel = new StandardKernel();
static JobHostConfiguration config;
static void Main(string[] args)
{
Environment.SetEnvironmentVariable("AzureWebJobsDashboard", "MySettings");
Environment.SetEnvironmentVariable("AzureWebJobsStorage", "MySettings");
BootStrapIoc();
config = new JobHostConfiguration();
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
var host = new JobHost(config);
host.RunAndBlock();
}
private static void BootStrapIoc()
{
Kernel.Load(Assembly.GetExecutingAssembly());
config = new JobHostConfiguration
{
JobActivator = new BrmJobActivator(Kernel)
};
}
}
UPDATE 2: I'm now getting the following error.
This error is thrown at the following line -- also see second image.
return _container.Get<T>();
UPDATE 3:
Here's the code in Functions.cs
file:
public class Functions
{
private static ISomeService1 _someService1;
private static ISomeService2 _someService2;
private static IConfiguration _configuration;
public Functions(ISomeService1 someService1, ISomeService2 someService2, IConfiguration configuration)
{
_someService1 = someService1;
_someService2 = someService2;
_configuration = configuration;
}
public async Task ProcessQueueMessage([QueueTrigger("my-brm-queue")] QueueMessage message, TextWriter log)
{
// Consume service
_someService1.DoSomething(message);
}
}
UPDATE 4: Here's the code in Ninject bindings class:
public class NinjectBindings : Ninject.Modules.NinjectModule
{
IConfiguration Configuration;
public override void Load()
{
// Bind to IConfiguration
var builder = new ConfigurationBuilder();
builder.SetBasePath(Directory.GetCurrentDirectory());
builder.AddJsonFile("appsettings.json");
Configuration = builder.Build();
Bind<IConfiguration>().ToMethod(ctx => {
return Configuration;
});
// Create instances of clients
var docDbClient = new ClassLibrary1.DocumentDbClient(Configuration);
var tsClient = new ClassLibrary2.TableStorageClient(Configuration);
// Bind Services
Bind<ISomeService1>().To<SomeService1>();
Bind<ISomeService2>().To<SomeService2>();
// Bind Repositories
Bind<IRepository1>().To<Repository1>();
Bind<IRepository2>().To<Repository2>();
}
}
After instantiating the
JobHostConfiguration
from theBootStrapIoc
method, you re-instantiate it from themain
method.Just remove this line in your
main
method: