Git Product home page Git Product logo

azure-function-autofac-dependency-injection's People

Contributors

adrianpell avatar babybalooga avatar bcnzer avatar bradtglass avatar dependabot[bot] avatar guillaumeguerra avatar lxalln avatar rawrspace avatar supereddie avatar thorhelms avatar youphulsebos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

azure-function-autofac-dependency-injection's Issues

Expose the container, or an ILifetimeScope.

I have a complex function, with a rather elaborated object tree it initializes. In order to monitor events in the objects using Application Insights, I need to pass the ExecutionContext.InvocationId I receive in the function to all classes, because that's what App Insights uses to correlate all events from the same invocation. see Monitor Azure Functions for details. So I wrap the InvocationId in a class, and I need to pass the same instance around to all of my classes. But since your package resolves instances from the container and not from a LifetimeScope, the default, InstancePerDependency lifetime is used, and classes are injected with a new instance of the wrapper instead of the one I initialized in the function.

The work around I made was to use reflection to access the private containers dictionary in DependencyInjection and call BeginLifetimeScope() on it. Then, I resolve objects from the scope instead of injecting them to the function with [Inject] attribute, wrapping most of the function with one big using block.

My current code looks something along the lines of

[FunctionName("messages")]
public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req,
    ILogger log, ExecutionContext context)
{
    using (ILifetimeScope scope = BeginLifetimeScope())
    {
        //we resolve from the container and not inject because we need to control the lifetime scope of the objects.
        IApmService apmService = scope.Resolve<IApmService>();
        InitializeApmService(apmService, context.InvocationId);
        //function code here...
        return req.CreateResponse(HttpStatusCode.Accepted);
    }
}

private static void InitializeApmService(IApmService apmService, Guid invocationId)
{
    apmService.OperationId = invocationId.ToString();
}

private static ILifetimeScope BeginLifetimeScope()
{
    FieldInfo containerField = typeof(DependencyInjection).GetField("containers", BindingFlags.Static | BindingFlags.NonPublic);
    if (containerField != null && containerField.GetValue(null) is Dictionary<string, IContainer> containers)
    {
        return containers.TryGetValue(nameof(MainFunction), out IContainer container)
            ? container.BeginLifetimeScope()
            : throw new Exception($"{nameof(MainFunction)} container not found");
    }
    throw new Exception("Error resolving LifetimeScope");
}

Describe the solution you'd like
Option 1 is to resolve objects from a ILifetimeScope in DependencyInjection. The problem with this approach is that the scope should be disposed, and I don't know how you can detect when the function ended execution to call the Dispose() method.

Option 2 is to expose a BeginLifetimeScope() method, perhaps accepting a class name (the "functionName" parameter the configuration class constructor should accept), and let the user control the scope.

Configuration Settings not picked up from appsettings.json file

Describe the bug
We are using DI and IConfiguration to load the configuration settings from the config file. Apparently the local debugging reads the content from the appsettings.json file but when we deploy the Azure Function, it doesn't read the settings from the appsettings.json. We had to define all the setiings as Application Setting to make it work.

To Reproduce
Steps to reproduce the behavior:

    public class DIConfig
    {
        public DIConfig(string functionName)
        {
            DependencyInjection.Initialize(
                builder =>
            {
                builder.RegisterModule(new RegisterModule());
            },
                functionName);
        }
    }
    public class RegisterModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<Repository>().As<IRepository>();
            builder.RegisterType<IBusiness>().As<IBusiness>();
            builder.RegisterInstance(ConfigManager()).As<IConfiguration>().SingleInstance();
        }

        private static IConfigurationRoot ConfigManager()
        {
            return new ConfigurationBuilder()
                               .SetBasePath(Directory.GetCurrentDirectory())
                               .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                               .AddEnvironmentVariables()
                               .Build();
        }
    }
   [DependencyInjectionConfig(typeof(DIConfig))]
    public static class TestFunction
    {
        [FunctionName("TestFunction")]
        public static async Task<IActionResult> GetDetailsAsync([HttpTrigger(AuthorizationLevel.Function, "get", Route = "values/{id}")]HttpRequestMessage req, string id, [Inject]IBusiness business)
        {
            // code
        }
     }

Expected behavior
It should read the data from the configuration file. Any help is really appreciated.

Constructor Injection

Is it possible to add support for constructor injection? I'm unsure of the technicals of how this is built, so apologies if this is a dumb question.

RegisterLoggerFactory doesnt work

Describe the bug
I'm using your new RegisterLoggerFactory extension in order to inject ILogger on my classes.

However, I can inject it but I cannot log anything in my classes.

keep in mind that:

  • if I inject the ILogger in functions, they logs
  • if I try to create my custom ILoggerFactory in the IOCconfig instead of using the 2nd parameter (the one after functionName) then it works

What I'm doing wrong?

To Reproduce
Steps to reproduce the behavior:

  1. Inject RegisterLoggerFactory
  2. Inject ILogger somewhere
  3. Log something

Expected behavior
I should see logs in my console

Inject ILogger/TraceWriter to services

First of all, thanks for putting this pkg together, it's awesome.

Now, this is more like a question than a feature request.

Have you found a way to inject the ILogger or TraceWriter into command/queries, so you don't need to log in the function itself?

[FunctionName(nameof(DoSomething))]
public static async Task DoSomething(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]HttpRequest req,
    //use this inside the DoSomethingCommand 
    ILogger log,
    [Inject] IDoSomethingCommand cmd)
{
    await cmd.Execute();
}

public class DoSomethingCommand : IDoSomethingCommand
{
    private readonly ILogger _logger;
    public DoSomething(ILogger logger){
        _logger = logger;
    }
    public async Task Execute(){
        _logger.LogInformation("Something was executed");
    }
}

package installation error.

I am getting this error when I install your nuget package.

Install-Package : Version conflict detected for Microsoft.Azure.WebJobs. Reference the package directly from the project to resolve this issue.
Medirecords.Functions -> AzureFunctions.Autofac 2.0.0 -> Microsoft.Azure.WebJobs (>= 2.1.0-beta4)
Medirecords.Functions -> Microsoft.NET.Sdk.Functions 1.0.2 -> Microsoft.Azure.WebJobs (= 2.1.0-beta1).

  1. If I have a JSON.net installed, I got this error.

Restoring packages for C:\TelstraHealth\healthbiz\Medirecords\Medirecords.Functions\Medirecords.Functions.csproj...
Detected package version outside of dependency constraint: Microsoft.NET.Sdk.Functions 1.0.2 requires Newtonsoft.Json (= 9.0.1) but version Newtonsoft.Json 10.0.3 was resolved.
Install-Package : Version conflict detected for Microsoft.Azure.WebJobs. Reference the package directly from the project to resolve this issue.

"A second operation started on this context before a previous asynchronous operation completed"

I am using AzureFunctions.Autofac to inject into my Azure Functions web api. An example of the config:

  public class DIConfig
    {
        public DIConfig()
        {
            DependencyInjection.Initialize(builder =>
            {
                // DAL
                builder.Register<IDbContext>(c => new SecretCompanyContext()).InstancePerLifetimeScope();
                builder.RegisterType<SecretCompanyContext>().InstancePerLifetimeScope();
                builder.RegisterType<SecretCompanyContext>().As<ICartContext>().InstancePerLifetimeScope();
                builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();

                // Services               
                builder.RegisterType<InventoryServices>().As<IInventoryServices>().InstancePerLifetimeScope();

                // Controllers ported from ASP.NET MVC Web API
                builder.RegisterType<InventoryController>().InstancePerLifetimeScope();
            });
        }

Then my Azure functions, I have one class that defines all methods in the API

    [DependencyInjectionConfig(typeof(DIConfig))]
    public class InventoryFunctions : FunctionsApi
    {
        [FunctionName("GetProductsByCategory")]
        // /inventory/categories/{id}/products
        public static async Task<HttpResponseMessage> GetProductsByCategory(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = "inventory/categories/{id}/products")]
            HttpRequestMessage req,
            TraceWriter log,
            int id,
            [Inject] InventoryController controller)
        {
            // do stuff
            var result = await controller.GetProductsByCategory(id);
            return JsonResponse(result, HttpStatusCode.OK);
        }

        [FunctionName("GetInventoryBySku")]
        // /inventory/skus?sku=ASDF&sku=ASDG&sku=ASDH
        public static async Task<HttpResponseMessage> GetInventoryBySku(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = "inventory")]
            HttpRequestMessage req,
            TraceWriter log,
            [Inject] InventoryController controller)
        {
            // do stuff
            var result = await controller.QueryInventoryBySkuList(skuList);
            return JsonResponse(result, HttpStatusCode.OK);
        }

        [FunctionName("UpdateProductsQuantity")]
        // /inventory
        // Post
        public static async Task<HttpResponseMessage> UpdateProductsQuantity(
            [HttpTrigger(AuthorizationLevel.Function, "put", Route = "inventory")]
            HttpRequestMessage req,
            TraceWriter log,
            [Inject] InventoryController controller)
        {
            // do stuff
            var inventoryProducts = await req.Content.ReadAsAsync<List<InvProductOperation>>();
            var result = await controller.UpdateAvailableProductsQuantity(inventoryProducts);
            return JsonResponse(result, HttpStatusCode.OK);
        }

But I keep getting this error:

A second operation started on this context before a previous
asynchronous operation completed. Use 'await' to ensure that
any asynchronous operations have completed before calling
another method on this context. Any instance members are not
guaranteed to be thread safe.

I have verified that async and await are used properly, so following the error message's recommendation isn't fixing it. What appears to be the issue is that IDbContext is not honoring the InstancePerLifetimeScope as expected. Is this happening because I have more than one method in my InventoryFunctions class? Or is AzureFunctions.Autofac not threadsafe?

Microsoft.Azure.WebJobs.Host: Error indexing method 'Functions.xxxx'. mscorlib: Constructor on type 'xxx.xxx.Startup.AutofacConfig' not found

Hey,

After I update the package 'Microsoft.Extensions.Logging' the dependency injection stopped to work with the following error:

Microsoft.Azure.WebJobs.Host: Error indexing method 'Functions.xxxx'. mscorlib: Constructor on type 'xxx.xxx.Startup.AutofacConfig' not found

This is my DI constructor:

public AutofacConfig(string functionName, ILoggerFactory loggerFactory)
{
}

If I remove the ILoggerFactory, it works.
public AutofacConfig(string functionName)
{
}

Access request in DIConfig

I have a requirement to read the metadata from "HttpRequestMessage request" and pass it to parameter in a constructor using .WithParameters. Is it possible to access request parameter in DIConfig class?

Allow newer versions of Autofac to be used

At the moment I need to use Autofac.Extensions.DependencyInjection on my project in order to be able to use builder.Populate() and add services from the Microsoft Dependency Injection Framework like .AddHttpClient().

However, the latest release needs Autofac to be upgraded to 4.9.1. The project has a dependency on Autofac 4.2.1, which is making me have to use an older version of this nuget package (version 4.2.2).

Is there any reason why the dependency is Autofac=4.2.1 and not Autofac>=4.2.1? Version 4.2.1 was released almost three years ago.

Dependency resolution graph for injected services

Is your feature request related to a problem? Please describe.
To better understand and debug issues related to Dependency Injection, and also, it becomes easier to investigate when one understands the dependency resolution graph

Describe the solution you'd like
Autofac v6 release provides the ability to create resolution graph of injected services. Provide the ability to hook into container and subscribe to diagnostic events
DotComplexTrace

Describe alternatives you've considered

Additional context
Nuget: Autofac.Diagnostics.DotGraph

Registering PerFunctionScope

HI

I would like some items to have be registered as "InstanceFunctionScope".
I can use enable caching = false, but then this will affect all registrations.
If I use InstancePerLifetimeScope then I get a scope for the function, however Autofac "looses" the scope registrationin the child tasks.
In a controller the "InstancePerRequest" would be what i need. But this is not supported in the functions. Any thoughts to allowing a "InstanceFunctionScope" ?

Error with Autofac 4.7

Yesterday autofac 4.7 was released, however, your module tries to find autofac 4.6.2. As a result an error Could not load file or assembly 'Autofac, Version=4.6.2.0 is thrown.
I believe you should add an explicit dependency on autofac in .nuspec file.

License question

Is your feature request related to a problem? Please describe.
Is there a reason why this project is licensed as GPL 3.0? Autofac and other extensions are licensed as MIT.

Describe the solution you'd like
Change license to MIT

Additional context
If I understand it correctly, using a GPL 3.0 license means that anything built using this project would itself have to be licensed as GPL 3.0 in source form, etc. For a commercial project (or even an internal-only project) that's probably a showstopper. The MIT license, by contrast, is about as permissive as they get and would seem to be ideal here.

I have a PR related to per-function invocation resolution that I'd like to send you at some point.

Nuget package with netstandard2.0

Hi,

Could you publish a nuget package with netstandard2.0? This way I could use this package together with durable functions.

Thanks

Support for HttpRequestMessage parameter in DI class

Describe the solution you'd like

public class DIConfig
{
public DIConfig(string functionName, string baseDirectory, ILoggerFactory factory, HttpRequestMessage request)
{
DependencyInjection.Initialize(builder =>
{
builder.RegisterModule(new TestModule());
builder.Register(c => new DirectoryAnnouncer(baseDirectory)).As();
builder.RegisterLoggerFactory(factory);
}, functionName);
}
}

Adding support for HttpRequestMessage will enable different scenarios of DI container configuration.

Example

based on query parameters it would be possible in dynamic way configure and use different logic implementations

Ability to verify DI-configuration

Dependency injection is great for testing, but to ensure that the dependency injection itself won't fail during runtime, it would be nice to have a built in ability for the DI-library to verify the configuration, for instance by scanning a given assembly and attempting to resolve the dependencies.

My suggestion would be a 'DependencyInjection.VerifyConfiguration(Assembly assembly)' method, with inspiration in the following:

using System;
using System.Reflection;
using AzureFunctions.Autofac;
using AzureFunctions.Autofac.Configuration;
using TodoAppBackend;
using Xunit;

namespace TodoAppBackendTest
{
    public class DITest
    {
        [Fact]
        public void TestDependencyInjection()
        {
            var assembly = typeof(DIConfig).Assembly;
            var classes = assembly.GetTypes();

            foreach (var c in classes)
            {
                var cAttr = c.GetCustomAttribute<DependencyInjectionConfigAttribute>();

                var injectAttrFound = false;

                var methods = c.GetMethods(BindingFlags.Public | BindingFlags.Static);
                foreach (var method in methods)
                {
                    var ps = method.GetParameters();
                    foreach (var param in ps)
                    {
                        var injectAttr = param.GetCustomAttribute<InjectAttribute>();

                        if (injectAttr == null)
                        {
                            continue;
                        }

                        // If this fails, DI-container is not set up on the class
                        Assert.NotNull(cAttr);

                        injectAttrFound = true;
                        var functionname = $"testfunction-{Guid.NewGuid()}";

                        // If this fails, the DI-config doesn't have the proper constructor
                        Activator.CreateInstance(cAttr.Config, functionname);

                        // If this fails, dependencies are not set up properly in the configuration
                        DependencyInjection.Resolve(param.ParameterType, injectAttr.Name, functionname);
                    }
                }

                if (!injectAttrFound)
                {
                    // If this fails, there is a DI-container but nothing to inject
                    Assert.Null(cAttr);
                }
            }

            Assert.True(true); // Dummy assertion to ensure that the test doesn't fail
        }
    }
};

If you like the idea, I would not be opposed to creating the feature.

Constructor not found for DI class with ctor signature DIConfig(string functionName, string baseDirectory, ILoggerFactory factory)

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. Implement function v3 according to documentation in the project
  2. Implement test according to documentation

Expected behavior
Test passes

Current behaviour:

Message:
Test method TestProject1.UnitTest1.TestMethod1 threw exception:
System.MissingMethodException: Constructor on type 'FunctionApp1.DIConfig' not found.
Stack Trace:
RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
DependencyInjection.VerifyConfiguration(Type type, Boolean verifyUnnecessaryConfig)
UnitTest1.TestMethod1() line 13

Additional context
Add any other context about the problem here.

Register existing services when creating containers

I would like to have existing services that are registered by Azure Functions to be ported over to the created Autofac containers. The IWebJobsStartup implementation exposes 73 services in Microsoft.NET.Sdk.Functions 1.0.19. For example, the one I'm interested in is ILoggerFactory.

image

I port the existing services in an ASP.Net project by referencing the Autofac.Extensions.DependencyInjection package which provides a builder.Populate(services) method (see https://github.com/autofac/Autofac.Extensions.DependencyInjection/blob/develop/src/Autofac.Extensions.DependencyInjection/AutofacRegistration.cs#L50).

The problem this solves is that the Functions platform already has out of the box registrations that custom code could then build upon. These "existing" services are not currently available via the Autofac containers.

Pass a ContainerBuilder in

Is your feature request related to a problem? Please describe.
Looks like a ContainerBuilder is created every time a function is invoked, which is a bit slow, would you consider to let function to pass in a ContainerBuilder instead?

Describe the solution you'd like
To have a overloading method that be able to pass in a ContainerBuilder

public static void Initialize(
     ContainerBuilder userPreConfiguredBuilder,
      string functionClassName,
      Action<IContainer> containerAction = null)

And the SetupContainerBuilder will look something like that

private static IContainer SetupContainerBuilder(
     ContainerBuilder builder,
      Action<IContainer> containerAction = null)
    {
      
      IContainer container = containerBuilder.Build();
      if (containerAction != null)
        containerAction(container);
      return container;
    }

Happy to contribute codes, let me know what are your thought, looking forward to hear from you

Thanks
Eddy

README.md has wrong information for Named instances registering in ContainerBuilder

Describe the bug
In the readme file, the section where it shows an example where we can register named instance contains error. We need to specify As() before the named instance for proper named registration

To Reproduce
Steps to reproduce the behavior:

  1. Create a azure funcitons project

  2. Create a DIConfig class and paste the code in examples

  3. Create the related classes and interfaces skeletons that are used in the sample

  4. Use [Inject("")] parameter in your sample funciton

  5. Debug and break in the function body.

Expected behavior
The object is injected

Observed behavior
The object is null

Autofac Named Instances aren't supported

Currently if you register multiple concrete classes with the same interface type it will not inject the correct one because you don't register the class.

Perhaps you could move the resolver to be above the class level and inject the resources at that level or add a property to the attribute for name being optional and resolve it that way.

IOptions DI in Azure Function

Hi,

I would like to resolve IOptions using AzureFunctions.Autofac nuget package.

Usually in a webapi, we can use:

    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        [...]

        services.Configure<MySettings>(config.GetSection("My"));

        // Autofac
        var builder = new ContainerBuilder();
        builder.Populate(services);

        [...]
    }

But in an Azure function, the populate option is not available throw the nuget package Autofac.Extensions.DependencyInjection:
image

How are you available to access to IOptions in Azure function using Autofac DI?

Thanks for your help.

Source: autofac/Autofac#991

QueueTrigger - it doesn't work

I have a queue triggered azure function. I am registering all of my query handlers as below. It doesn't call the Run if I add the [inject] parameter even the azure function has been read the message from queue.

            {
                builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
                       .AsClosedTypesOf(typeof(IQueryHandler<,>)).AsImplementedInterfaces();
            });

[2/27/2018 1:34:19 PM] A ScriptHost error has occurred
[2/27/2018 1:34:19 PM] Exception while executing function: PatientSync. Microsoft.Azure.WebJobs.Host: Exception binding parameter 'queryProcessor'. Autofac: An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = QueryProcessor (ReflectionActivator), Services = [MyAzureFunc.IQueryProcessor], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope ---> None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyAzureFunc.QueryProcessor' can be invoked with the available services and parameters:
[2/27/2018 1:34:19 PM] Cannot resolve parameter 'Autofac.Core.Container container' of constructor 'Void .ctor(Autofac.Core.Container)'. (See inner exception for details.). Autofac: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyAzureFunc.QueryProcessor' can be invoked with the available services and parameters:
[2/27/2018 1:34:19 PM] Cannot resolve parameter 'Autofac.Core.Container container' of constructor 'Void .ctor(Autofac.Core.Container)'.
[2/27/2018 1:34:19 PM] Exception while executing function: PatientSync
[2/27/2018 1:34:19 PM] Exception while executing function: PatientSync. Microsoft.Azure.WebJobs.Host: Exception binding parameter 'queryProcessor'. Autofac: An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = QueryProcessor (ReflectionActivator), Services = [MyAzureFunc.IQueryProcessor], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope ---> None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyAzureFunc.QueryProcessor' can be invoked with the available services and parameters:
[2/27/2018 1:34:19 PM] Cannot resolve parameter 'Autofac.Core.Container container' of constructor 'Void .ctor(Autofac.Core.Container)'. (See inner exception for details.). Autofac: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyAzureFunc.QueryProcessor' can be invoked with the available services and parameters:
[2/27/2018 1:34:19 PM] Cannot resolve parameter 'Autofac.Core.Container container' of constructor 'Void .ctor(Autofac.Core.Container)'.
[2/27/2018 1:34:19 PM] Function completed (Failure, Id=1fc4029c-d606-4b9b-b9ef-10a2c81f2951, Duration=233ms)

Inject function parameters

Today, I started working with this Nuget package, and got the injection to work.

Previously, I used another DI solution, however, I needed to create a container manually in the Azure Function, and resolve "the first in line".
Fortunately, with this solution, this isn't needed anymore.

However: in my previous setup, I could give the ILogger (Microsoft.Extensions.Logging) - given as a parameter to the Azure Function - into a wrapper to my container. The wrapper implemented my own "ILogger", as I didn't want to expose the Microsoft.Extensions library to other assemblies.

Is it possible to let the ILogger (even better all parameters of the Azure Function) being injected into a constructor?

RegisterAssemlyTypes now working for ClosedTypes

Hi

We are using the same register code lines for our WebApi and Azure Function V2.
But the below dependency is not getting resolved in Azure function instance where as seems to be working fine in WebApi
AutoFac - 4.6.2

//For Core
var assemblies = Assembly
.GetEntryAssembly()
.GetReferencedAssemblies().Select(a=> Assembly.Load(a.Name)).ToArray();

//For Framework
var assemblies = System.Web.Compilation.BuildManager.GetReferencedAssemblies().Cast().ToArray();

builder.RegisterAssemblyTypes(assemblies)
.AsClosedTypesOf(typeof(IContainerRetriever<,>))
.AsImplementedInterfaces();

//Abstract Class
public abstract class BaseContainerRetriever<TContract, TContainerFilter, TEntity> : IContainerRetriever<TContainerFilter,TContract> where TContract : class where TContainerFilter: class
{
}
//Final Implemented class
public class AssetContainerRetriever : BaseContainerRetriever<Inventory, InventoryContainerFilter , InventoryData>
{
}

IContainerRetriever<Inventory,InventoryData> is not getting resolved.

Please help me out here.

Regards
Hari

Upgrade to Core 3.1

We've been using the package successfully with Azure functions running on 2.2 Core, but have recently began upgrading to 3.0 (and then eventually 3.1). This package kept us from upgrading successfully - but it is integral to our process.

Do you have plans on upgrading this to Core 3.0 + ?

ILifetimeScope not disposed on V1 functions

Describe the bug
After following the documentation for adding DI to a V1 function app, the ILifetimeScope objects are not disposed after a function has finished executing causing memory 'leaks'. A function app actually crashed for running out of memory.

To Reproduce
Steps to reproduce the behavior:

  1. Make a simple DI config that writes something OnRelease:
public class DependencyInjectionSetup
{
  public DependencyInjectionSetup(string functionName)
  {
    DependencyInjection.Initialize(builder =>
    {
      builder.RegisterType<SomeClass>().As<SomeInterface>().OnRelease(c => System.Diagnostics.Trace.WriteLine("Releasing SomeInterface"));
    }
  }
}
  1. Add [DependencyInjectionConfig(typeof(DependencyInjectionSetup))] to the function static class
  2. [Inject] the SomeInterface as a parameter in the function
[FunctionName(nameof(TriggerTest))]
public static async Task TriggerTest(
  [TimerTrigger("0 */1 * * * *")] TimerInfo timer, 
  TraceWriter log,
  [Inject] SomeInterface someInterfaceInstance)
{
  ///
}
  1. After the function has run, notice that there is no message in the debug output, indicating that the ILifetimeScope was not disposed.

Expected behavior
An message in the debug output 'Releasing SomeInterface'

Additional context
A crude fix that seems to work: Use the FunctionInvocationFilterAttribute in a similar way the ScopeFilter is used:

public sealed class ScopeFilterAttribute : FunctionInvocationFilterAttribute
{
  public override Task OnExecutedAsync(FunctionExecutedContext executedContext, CancellationToken cancellationToken)
  {
    RemoveScope(executedContext.FunctionInstanceId);
    return Task.CompletedTask;
  }

  public override Task OnExecutingAsync(FunctionExecutingContext executingContext, CancellationToken cancellationToken)
  {
    return Task.CompletedTask;
  }

  private static void RemoveScope(Guid functionInstanceId)
  {
    DependencyInjection.RemoveScope(functionInstanceId);
  }
}

Then apply this attribute to the Function class, similar to DependencyInjectionConfig. Now the 'Releasing SomeInterface' will appear in the debug output after the function has executed.

This may not be correct approach, but for now it seems to work here.

Implementing ILogger

Using this framework what is the recommended way of implementing ILogger so that it can be used in all services?

Configuration Dependency Injection

builder.Register(cfg =>
{
                    var config = new ConfigurationBuilder()
                        .SetBasePath(Directory.GetCurrentDirectory())
                        .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                        .AddEnvironmentVariables()
                        .Build();
                    MySection asc = new MySection();
                    config.GetSection("MySection").Bind(asc);
                    return Options.Create(asc);
}).As<IOptions<MySection>>();

Trying to do something like this but dont have any access to ExecutionContext to get the current directory

Have you got any recommendations

Resolve method errors out

Describe the bug
Trying to write test to ensure that all dependencies are registered, and to make sure I don't have false positive, I left out registration of some types needed to construct type I am testing. VerifyConfiguration still passes. So I looked at "Resolve" and when I use that it fails with a message that I did not register component I am trying to resolve.

Here is my test:

[Theory]
[InlineData(typeof(PaymentToMerchantProcessor))]
 public void can_wire_up_type(Type t)
 {
        var config = new DIConfig("ProcessPaymentToMerchantCompletedEvent");

        DependencyInjection.VerifyConfiguration(t);

        DependencyInjection.Resolve(t, "name", "ProcessPaymentToMerchantCompletedEvent", Guid.NewGuid());
}

Instances are resolved from the container, instead of from a lifetime scope

Your code resolves instances like this:


where container is the IContainer interface. However, the Autofac documentation has this to say about resolving instances from the container:

While it is possible to resolve components right from the root container, doing this through your application in some cases may result in a memory leak. It is recommended you always resolve components from a lifetime scope where possible to make sure service instances are properly disposed and garbage collected.

Resolving Services

So you should resolve the instances from whatever lifetime scope which is appropriate for a function, and not directly from the container.

support function instance scoped DI

Is your feature request related to a problem? Please describe.
Project supports function level configs. but there isnt a way to do instance specific scoped services. for eg if instead of TraceWriter an ILogger instance had to be injected.

Describe the solution you'd like
For the function itself as well as the other classes that are involved in processing a particular function execution, there should be a way to register a class so that for a given function invocation, the same class instance is returned. In other words the lifetime of this type of object should be for the function invocation. "function request scope". Would this be possible ?

Container instances do not cache

Is your feature request related to a problem? Please describe.
Hi there, thanks for your work, just wondering if you have any plan to not to have container instances cached? I am looking for a brand new container every time a function triggered. Thanks

Autofac with Azure Functions with IWebJobsBuilder for constructor DI

We are trying Dependency Injection with Autofac to our Azure Functions. We have a startup class [assembly: WebJobsStartup(typeof(Startup))] which calls the ConfigureServices. The out-of-the-box dependency injection with .net core works fine, but we are trying Dependency Injection with Autofac and we are unable to inject our service classes into Azure Function constructor.
When we try to Resolve the dependencies using "Resolve" keyword of IContainer from Autofac, I'm able to resolve the service. Any help in this regard would be highly appreciated.

Not working with Azure durable activity function

Hi,
I'm using this library in my Azure durable functions app.
I've defined my DIConfig as follows, and when the function app starts I can see the ctor of this class is called with my activity function class name as functionName parameter value.

 public  class DIConfig
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="DIConfig"/> class.
        /// </summary>
        /// <param name="functionName">
        /// The function name.
        /// </param>
        public DIConfig(string functionName)
        {
            DependencyInjection.Initialize(
                containerBuilder =>
                    {
                        containerBuilder.RegisterType<AuthenticationService>().As<IOAuthService>();
                        containerBuilder.RegisterType<GenericAPIService>().As<IGenericAPIService>();
                        containerBuilder.RegisterType<EmailTemplateNotificationService>().As<IEmailTemplateNotificationService>();
                        containerBuilder.RegisterType<AicGenericSdk>().As<IAicGenericSdk>();
                       containerBuilder.RegisterType<AgreementExpiryService>().As<IAgreementExpiryService>();
                        containerBuilder.RegisterType<EmailReminderService>().As<IEmailReminderService>();
                    },
                functionName);
        }
    }

Below is the code of my activity function , where I'm want to use DI

  [DependencyInjectionConfig(typeof(DIConfig))]
    public static  class EmailReminderActivities
    {
     
        [FunctionName("A_GetAgreementsForEmailReminder")]
        public static List<AgreementModel> GetAgreementsForEmailReminder(
            [ActivityTrigger] string input,
            TraceWriter log,
            [Inject] IEmailReminderService emailReminderService)
        {
            
          return (List<AgreementModel>)emailReminderService.GetAgreementsForReminderDate(input);
        }
    }

This is the error I'm getting

A ScriptHost error has occurred
[6/25/2018 8:20:44 AM] Exception while executing function: A_GetAgreementsForEmailReminder. Microsoft.Azure.WebJobs.Host: Exception binding parameter 'emailReminderService'. AzureFunctions.Autofac: DependencyInjection.Initialize must be called before dependencies can be resolved.
If I would have not use DI then this is how I would have initialize my EmailReminderService

var emailReminderSvc = new EmailReminderService(new AicGenericSdk(new GenericAPIService(new AuthenticationService()),null ));

I hope I've registered dependencies in the right order.
Please help

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.