azure-webjobs-sdk: Breaking change in ExtensionConfigContext
As noted here a lot of dependency injection stuff is build that relies on getting the JobHostConfiguration
from the ExtensionConfigContext
. With the new beta8 package the Config is gone. This is the old beta5 code:
public class ExtensionConfigContext : FluentConverterRules<Attribute, ExtensionConfigContext>
{
public ExtensionConfigContext();
public JobHostConfiguration Config { get; set; }
public FluentBindingRule<TAttribute> AddBindingRule<TAttribute>() where TAttribute : Attribute;
[Obsolete("preview")]
public Uri GetWebhookHandler();
}
Now we are not able to build an Inject binding to inject certain dependencies into our functions. Like we did before:
public class InjectConfiguration : IExtensionConfigProvider
{
public void Initialize(ExtensionConfigContext context)
{
var rule = context
.AddBindingRule<InjectAttribute>()
.Bind(new InjectBindingProvider());
var registry = context.Config.GetService<IExtensionRegistry>();
var filter = new ScopeCleanupFilter();
registry.RegisterExtension(typeof(IFunctionInvocationFilter), filter);
registry.RegisterExtension(typeof(IFunctionExceptionFilter), filter);
}
}
Do you have any alternatives for dependency injection? And if so please show an example.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 7
- Comments: 36 (1 by maintainers)
I have published an example in this repository: https://github.com/DibranMulder/azure-functions-v2-dependency-injection
@DibranMulder I think you have seen the new extension model, and the DI changes.
With those changes to create a extension now you first need to create a startup class, using [assembly:WebJobsStartup] and implementing IWebJobsStartup interface, there you can add your own services to the builder via builder.Services and register your extensions config provider:
Then in your IExtensionConfigProvider you can inject any dependencies via constructor injections, for example, binding, bindingproviders, or any custom dependency.
However you can’t request an IExtensionRegistry inside an IExtensionConfigProvider due to a circular dependency issue, breaking the host with a StackOverflowException #1872.
Looking at the latest Filter tests you can register your filter with DI in the Configure method of the Startup class, as an IFunctionFilter with the Singleton lifetime and the Web Jobs framework will figure out if it is a Pre, Post or Exception filter:
To get the host to load the extension, it must be registered in bin/extensions.json file, in JavaScript or Java via
func extensions
command, and in C# the SDK 1.0.19 does it automatically at build time for the current function project or any dependency (ProjectReference or PackageReference) in the current project.I have adapted your samples to use the built-in IServiceProvider, also configuring the services into the framework’s own container instance, and creating scopes before function calls.
FYI
I found this reference in case somebody is interested, organic DI still work in progress.
Azure Functions Live Stream from 27th September 2018 (from 27th minute - till around 37th minute) https://youtu.be/7mAzMYOP9NY?t=27m19s
Example from the video (Note again, organic DI not yet available).
No static methods 😄.
@DibranMulder you don’t need to build the service collection, you can add your services, then they will be injected in your extension config provider, including the current IServiceProvider:
That way you can mix and match your app services with those coming from the framework. The azure function host controls now the lifetime of the root service provider, and builds it before calling any IExtensionConfigProvider.
I also had to only use the IWebJobsBuilder.Services as the injection point to add the extension for the binding -- adding my services in to that didn't work
@ryanspletzer I didn’t notice that behavior, maybe it was caused by the early building of ServiceProvider. however I did saw some subtle differences in behavior between the Webjobs SDK, the ASP.NET Service Provider and the current DI implementation in WebJobs.WebScript (aka functions), I suspect that what is causing the differences is the extraneus choice of using DryIOC behind the scenes in the functions hosts. Those differences forced me to rollback to a separate service collection for application services and only use the built in one for framework things (like filters),
I will open a new issue soon.Issue opened: https://github.com/Azure/azure-functions-host/issues/3399Update: I see that @cResults already published how to inject dependencies into IExtensiongConfigProvider.
@ryanspletzer I was able to get a logger into the servicecollection. i had a number of iterations that LOOKED a lot better, but this one works for now.
This appears to be working. I say appears because my test requires an ILogger, which I’m still tyring how to create in the current environment. Anyway, when InjectConfiguration.Initialize is called, _InjectBindingProvider was populated with the instance registered in the start up.
@ryanspletzer mine is based on @BorisWilHems as well. Then followed the File/Folder layout from https://github.com/Azure/azure-webjobs-sdk-extensions
Thanks got it to work! The code below might be interesting for people reading this thread. Do you see any bad practices or things you should do different?
Yes it works with AzFunc Here is my webjobs DI extension https://github.com/espray/azure-webjobs-sdk-extensions
@chris31389 I also had issues with DI and implement simple DI base on @ielcoro answer : https://github.com/ArtemTereshkovich/DependencyInjectionAzureFunction