Giter Club home page Giter Club logo

stashbox's Introduction

Stashbox

Appveyor Build Status GitHub Workflow Status Sonar Tests Sonar Coverage Sonar Quality Gate Sourcelink

Stashbox is a lightweight, fast, and portable dependency injection framework for .NET-based solutions. It encourages the building of loosely coupled applications and simplifies the construction of hierarchical object structures. It can be integrated easily with .NET Core, Generic Host, ASP.NET, Xamarin, and many other applications.

Github (stable) NuGet (stable) Fuget (stable) NuGet (pre-release)
Github release NuGet Version Stashbox on fuget.org Nuget pre-release

Core Attributes

  • ๐Ÿš€ Fast, thread-safe, and lock-free operations.
  • โšก๏ธ Easy-to-use Fluent configuration API.
  • โ™ป๏ธ Small memory footprint.
  • ๐Ÿ”„ Tracks the dependency tree for cycles.
  • ๐Ÿšจ Detects and warns about misconfigurations.
  • ๐Ÿ”ฅ Gives fast feedback on registration/resolution issues.

Supported Platforms

  • .NET 5+
  • .NET Standard 2.0+
  • .NET Framework 4.5+
  • Mono
  • Universal Windows Platform
  • Xamarin (Android/iOS/Mac)
  • Unity

Contact & Support

  • Join the chat at https://gitter.im/z4kn4fein/stashbox Slack
  • Create an issue for bug reports and feature requests.
  • Start a discussion for your questions and ideas.
  • Add a โญ๏ธ to support the project!

Extensions

Benchmarks


Powered by Jetbrains' Open Source License

Jetbrains

stashbox's People

Contributors

dependabot[bot] avatar mgth avatar schuettecarsten avatar z4kn4fein 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  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  avatar  avatar  avatar

stashbox's Issues

Fix the container extension registration

When an extension implements both the IPostBuildExtension and the IRegistrationExtension interface at the same time, the extension invocation not working properly

WithUnknownTypeResolution breaks Constructor selection rules

I have a class that implements these two constructors:

public LoggerFactory(IEnumerable<ILoggerProvider> providers, LoggerFilterOptions filterOptions)
public LoggerFactory(IEnumerable<ILoggerProvider> providers, IOptionsMonitor<LoggerFilterOptions> filterOption)

Given there is a service registration for IEnumerable<ILoggerProvider> and for IOptionsMonitor<LoggerFilterOptions>, but no registration for LoggerFilterOptions. If the container is configured without WithUnknownTypeResolution, everything works fine, the second constructor is selected. But if WithUnknownTypeResolution is used, then the first constructor is choosed, regardless whether the second constructor is fully resolvable or not.

I would expect that unknown type resolution only runs if no constructor matches completely.

Possibility of WCF Extension? (enhancement/question)

Good Day,

I've been following up and coming IoC containers, one of w for a while now; this led me is yours and I was curious if you had any plans on creating a "stashbox" extension for the wcf service platform. I have sufficient experience in "IoC" concepts and would be willing to start the groundwork for such an endeavor if you're interested.

Either way, I've been very impressed by the work you've done with stashbox over the last couple months, here's hoping it gets some traction within the foreseeable future.

parent-child resolution (egg-chicken)

let's say we have an egg-chicken case we would like to handle as follows;

   public interface IEgg
    {
        IChicken Chicken { get; set; }
    }

    public interface IChicken
    {
        IEgg Egg { get; set; }
    }

    public class Chicken : IChicken
    {
        public IEgg Egg { get; set; }
    }

    public class Egg : IEgg
    {
        public Egg(IChicken chicken)
        {
            Chicken = chicken;
        }

        public IChicken Chicken
        {
            get;
            set;
        }
    }

with unity ioc it's possible with;

public void BuildObjectGraphWithCircularDependency()
{
    var container = new UnityContainer();

    container.RegisterType<IChicken, Chicken>(new PerResolveLifetimeManager(), new InjectionProperty("Egg"));
    container.RegisterType<IEgg, Egg>();

    var chicken = container.Resolve<IChicken>();

    Assert.AreSame(chicken, chicken.Egg.Chicken);
}

( code from http://sharpfellows.com/post/Unity-IoC-Container- )

is this also possible with stashbox?

latest stashbox version (2.5.7) failing with SignalR

I'm not sure what all information you need, but I upgraded stashbox last Friday via NuGet to v2.5.7, and since that time my project doesn't work. It appears to be failing trying to use the OWIN SignalR container - an exception is thrown at: app.UseStashboxSignalR(container, configSignalR); The exception is:

System.MissingMethodException was unhandled by user code
HResult=-2146233069
Message=Method not found: 'Stashbox.Infrastructure.IDependencyRegistrator Stashbox.DependencyRegistratorExtensions.RegisterSingleton(Stashbox.Infrastructure.IDependencyRegistrator, System.Object)'.
Source=Stashbox.AspNet.SignalR.Owin
StackTrace:
at Stashbox.Infrastructure.AppBuilderSignalRExtensions.AddOwinSignalR(IStashboxContainer container, HubConfiguration config, Assembly[] assemblies)
at Owin.AppBuilderSignalRExtensions.UseStashboxSignalR(IAppBuilder app, IStashboxContainer container, HubConfiguration config, Assembly[] assemblies)
at MyApi.Startup.Configuration(IAppBuilder app) in D:\dev\MyProject\MyApi\App_Start\Startup.cs:line 92
InnerException:

My project is a VS2015 Web Api and SignalR project.

Everything was working perfectly with v2.5.6.

Is there something I can do to fix this? What are the options? Do you need any more info?

Thank you.

injecting container itself?

I'm migrating from simpleinjector and have a factory like below;

    public class CoreFactory: ICoreFactory
    {
        private readonly StashboxContainer _container;

        public CoreFactory(StashboxContainer container)
        {
            _container = container;
        }

        public IEngine GetEngine()
        {
            return _container.Resolve<IEngine>();
        }

        public ILogManager GetLogManager()
        {
            return _container.Resolve<ILogManager>();
        }
    }

registered with;

_container.RegisterSingleton<ICoreFactory, CoreFactory>();

and resolving with;

var coreFactory = bootstrapper.Container.Resolve<ICoreFactory>(); // get core object factory.

but couldnt get it working? is it possible to inject the container itself?

Add named scopes

It would be nice if we could be able to create named scopes and differentiate registered services for them

context.WithFactory() fails with static factory methods

The following service registration generates an error on resolving in 2.7.5 when the factory method is static:

context.WithFactory(staticFactoryMethod)
	.WithSingletonLifetime()
	.WithoutDisposalTracking();

This works fine with 2.7.4.

Descriptive Registration Exception Information

It would be nice if exceptions during registration contained descriptive information, so it is easy to find out what mistake you made:

e.g: Resolve failed for a particular registration (forgot to register it). Exception message contains the exact constructor that was affected and which parameter/type. Autofac, for example, handles this pretty well.

Extend the configuration options

It would be nice if we could set injection properties, methods etc. during the registration in addition to the current auto injection and attribute solution.

Cleanup delegate for registrations

It would be nice to have an option to set a cleanup delegate for a registration which could be called when a scope is being disposed.

Mixture of named and non named registrations result in the wrong type resolved

If I have code like this:

sb.RegisterSingleton(typeof(ITest), typeof(Test));
sb.RegisterSingleton(typeof(ITest), typeof(Test1), "Test2");
sb.RegisterSingleton(typeof(ITest), typeof(Test2), "Test3");
var test = sb.Resolve<ITest>();

The result will be of type Test2 while I would expect it to be Test as I'm requesting it without a name I expect to get the nameless registration. If I rearrange the ordering I always get the last registered type.

Resolver factory invoke doesn't pass different parameters given when they're the same type

This may be a misuse and weird scenario but the behaviour is unexpected to me. When I use ResolveFactory and call DynamicInvoke passing in the parameters, if I have 2 parameters that are strings for example the last string I give will be used for both parameters.

Example type

public class Foobar : IFoo
{
        public Foobar()
        {
            
        }

        public Foobar(string x, string y)
        {
            Result = x + y;
        }

        public string Result { get; set; }
}

And my executing code is like this:

StashboxContainer container = new StashboxContainer();
container.RegisterType<IFoo, Foobar>();
var factory = container.ResolveFactory(typeof(IFoo), parameterTypes: new Type[] { typeof(string), typeof(string) });
Console.WriteLine(((IFoo)factory.DynamicInvoke("foo", "bar")).Result);

I would expect the output to be "foobar" however the output is "barbar". Even if I have other types with a mixture of strings and ints as the ctor params, it reuses the last string I give it for all string parameters.

NullReferenceException in ResolutionStrategy.cs when InjectionParameter value is null

This is in Stashbox 2.7.4 so forgive me if this has been found / fixed already.

I have an unusual edge case where I need to set an InjectionParameter with a null value. Upon attempting to resolve the service, a NullReferenceException is thrown.

After some debugging, I found that the problem area is in ResolutionStrategy.cs, line 43 (in BuildResolutionExpression):

var matchingParam = injectionParameters?.FirstOrDefault(param => param.Name == typeInformation.ParameterOrMemberName);
if (matchingParam != null)
    return matchingParam.Value.GetType() == typeInformation.Type
        ? matchingParam.Value.AsConstant()
        : matchingParam.Value.AsConstant().ConvertTo(typeInformation.Type);

You're already checking matchingParam for null, but the dependence on matchingParam.Value.GetType() and matchingParam.Value.AsConstant() both will cause NullReferenceExceptions here because matchingParam.Value is null.

Unfortunately I can't think of an immediate solution to this and it's definitely a strange use case. Fortunately since Stashbox is so flexible I should be able to find a workaround. :)

Unable to use nullable types with injection parameters

When I have a class with a nullable type in the constructor that needs an injection parameter, I get the following error trying to resolve it:

ArgumentException: Expression of type 'System.Int32' cannot be used for constructor parameter of type 'System.Nullable1[System.Int32]'
Parameter name: arguments[0]`

Here's the class:

    public interface IExample
    {
        int? ExampleProperty { get; }
    }

    public class ExampleClass : IExample
    {
        private readonly int? _exampleValue;

        public ExampleClass(int? exampleValue = null)
        {
            _exampleValue = exampleValue;
        }

        public int? ExampleProperty => _exampleValue;
    }

And here's the registration / configuration:

        public void ConfigureContainer(IStashboxContainer container)
        {
            container.Configure(config => config.WithOptionalAndDefaultValueInjection().WithCircularDependencyTracking());

            var someInt = (int?)123;

            container.Register<IExample, ExampleClass>(
                config => config.WithInjectionParameters(
                    new InjectionParameter
                    {
                        Name = "exampleValue",
                        Value = someInt
                    }));
        }

StashboxContainer.Resolve<T> missing

The documentation in the readme says to use "var wulfgar = container.Resolve();" to resolve a dependency but the method Resolve is missing from the StashboxContainer.Resolver.cs

Register Async Func

Hi. I'm trying to register something like this. Is it possible?

container.RegisterInstance<Func<string, Task<IValidator<string>>>>(async (schema) => await container.Resolve<ISchemaValidatorFactory>().FromFileAsync(schema));

Edit: It also looks like registering Func factories with parameters are not supported?

[Feature Request] ComposeBy / ICompositionRoot with an instance and / or injection

Currently when using ComposeBy, the class that implements ICompositionRoot is instantiated using System.Activator and it is not possible to easily pass parameters to the composition root.

A concept that I miss from StructureMap is the ability to use an instance of its Registry class (rather than just the registry class's type), so that it can be constructed with a few parameters before the container uses it to register anything.

It would be helpful if I had the ability to do either or both of these:

  • Call ComposeBy with an already-instantiated object that implements ICompositionRoot.
  • Allow the option of having Stashbox instantiate / buildup the composition root object(s) so that parameters / members can be injected into them.

variable '' of type 'System.IServiceProvider' referenced from scope '', but it is not defined

Hi am using stashbox with aspnet core 2.2 and Hangfire.

It is a multi tenant solution, where I spawn one hangfire instance for each tenant, and I hand each hangfire instance their own child container with their own specific registrations.

However when the hangfire server tries to start a job, and resolve a service, I get the following exception.

System.InvalidOperationException: variable '' of type 'System.IServiceProvider' referenced from scope '', but it is not defined
   at System.Linq.Expressions.Compiler.VariableBinder.Reference(ParameterExpression node, VariableStorageKind storage)
   at System.Linq.Expressions.Compiler.VariableBinder.VisitParameter(ParameterExpression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
   at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection`1 nodes)
   at System.Linq.Expressions.Compiler.VariableBinder.VisitLambda[T](Expression`1 node)
   at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda)
   at System.Linq.Expressions.ExpressionExtensions.CompileDelegate(Expression expression, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\Extensions\ExpressionExtensions.cs:line 42
   at Stashbox.Lifetime.SingletonLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\SingletonLifetime.cs:line 21
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Expressions.ConstructorSelector.TryBuildResolutionConstructor(ConstructorInformation constructor, ResolutionContext resolutionContext, IContainerContext containerContext, IServiceRegistration serviceRegistration, TypeInformation& failedParameter, Expression[]& parameterExpressions, Boolean skipUknownResolution) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 93
   at Stashbox.BuildUp.Expressions.ConstructorSelector.SelectConstructor(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, ConstructorInformation[] constructors) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 46
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateInitExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 138
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type serviceType) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 91
   at Stashbox.BuildUp.DefaultObjectBuilder.GetExpressionInternal(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\DefaultObjectBuilder.cs:line 32
   at Stashbox.BuildUp.ObjectBuilderBase.BuildDisposalTrackingAndFinalizerExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 52
   at Stashbox.BuildUp.ObjectBuilderBase.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 21
   at Stashbox.Lifetime.SingletonLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType)
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.ResolutionScope.Activate(ResolutionContext resolutionContext, Type type, Object name) in C:\projects\stashbox-0vuru\src\ResolutionScope.cs:line 272
   at Stashbox.ResolutionScope.Resolve(Type typeFrom, Boolean nullResultAllowed, Object[] dependencyOverrides) in C:\projects\stashbox-0vuru\src\ResolutionScope.cs:line 94
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions.<>c.<AddDataProtectionServices>b__2_0(IServiceProvider s)
   at (DT1 , IResolutionScope )
   at Stashbox.ResolutionScope.GetOrAddScopedItem(Int32 key, Object sync, Func`2 factory) in C:\projects\stashbox-0vuru\src\ResolutionScope.cs:line 180
   at Stashbox.Lifetime.SingletonLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\SingletonLifetime.cs:line 21
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Expressions.ConstructorSelector.TryBuildResolutionConstructor(ConstructorInformation constructor, ResolutionContext resolutionContext, IContainerContext containerContext, IServiceRegistration serviceRegistration, TypeInformation& failedParameter, Expression[]& parameterExpressions, Boolean skipUknownResolution) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 93
   at Stashbox.BuildUp.Expressions.ConstructorSelector.SelectConstructor(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, ConstructorInformation[] constructors) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 46
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateInitExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 138
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type serviceType) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 91
   at Stashbox.BuildUp.DefaultObjectBuilder.GetExpressionInternal(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\DefaultObjectBuilder.cs:line 32
   at Stashbox.BuildUp.ObjectBuilderBase.BuildDisposalTrackingAndFinalizerExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 52
   at Stashbox.BuildUp.ObjectBuilderBase.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 21
   at Stashbox.Lifetime.SingletonLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType)
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Expressions.ConstructorSelector.TryBuildResolutionConstructor(ConstructorInformation constructor, ResolutionContext resolutionContext, IContainerContext containerContext, IServiceRegistration serviceRegistration, TypeInformation& failedParameter, Expression[]& parameterExpressions, Boolean skipUknownResolution) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 93
   at Stashbox.BuildUp.Expressions.ConstructorSelector.SelectConstructor(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, ConstructorInformation[] constructors) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 46
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateInitExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 138
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type serviceType) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 91
   at Stashbox.BuildUp.DefaultObjectBuilder.GetExpressionInternal(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\DefaultObjectBuilder.cs:line 32
   at Stashbox.BuildUp.ObjectBuilderBase.BuildDisposalTrackingAndFinalizerExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 52
   at Stashbox.BuildUp.ObjectBuilderBase.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 21
   at Stashbox.Lifetime.ScopedLifetimeBase.GetFactoryExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\ScopedLifetimeBase.cs:line 38
   at Stashbox.Lifetime.ScopedLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\ScopedLifetime.cs:line 27
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Expressions.ConstructorSelector.TryBuildResolutionConstructor(ConstructorInformation constructor, ResolutionContext resolutionContext, IContainerContext containerContext, IServiceRegistration serviceRegistration, TypeInformation& failedParameter, Expression[]& parameterExpressions, Boolean skipUknownResolution) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 93
   at Stashbox.BuildUp.Expressions.ConstructorSelector.SelectConstructor(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, ConstructorInformation[] constructors) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ConstructorSelector.cs:line 46
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateInitExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 138
   at Stashbox.BuildUp.Expressions.ExpressionBuilder.CreateExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type serviceType) in C:\projects\stashbox-0vuru\src\BuildUp\Expressions\ExpressionBuilder.cs:line 91
   at Stashbox.BuildUp.DefaultObjectBuilder.GetExpressionInternal(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\DefaultObjectBuilder.cs:line 32
   at Stashbox.BuildUp.ObjectBuilderBase.BuildDisposalTrackingAndFinalizerExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 52
   at Stashbox.BuildUp.ObjectBuilderBase.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\BuildUp\ObjectBuilderBase.cs:line 21
   at Stashbox.Lifetime.ScopedLifetimeBase.GetFactoryExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\ScopedLifetimeBase.cs:line 38
   at Stashbox.Lifetime.ScopedLifetime.GetExpression(IContainerContext containerContext, IServiceRegistration serviceRegistration, IObjectBuilder objectBuilder, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Lifetime\ScopedLifetime.cs:line 27
   at Stashbox.Registration.ServiceRegistration.ConstructExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 169
   at Stashbox.Registration.ServiceRegistration.GetExpression(IContainerContext containerContext, ResolutionContext resolutionContext, Type resolveType) in C:\projects\stashbox-0vuru\src\Registration\ServiceRegistration.cs:line 116
   at Stashbox.Resolution.ResolutionStrategy.BuildResolutionExpression(IContainerContext containerContext, ResolutionContext resolutionContext, TypeInformation typeInformation, InjectionParameter[] injectionParameters, Boolean forceSkipUnknownTypeCheck) in C:\projects\stashbox-0vuru\src\Resolution\ResolutionStrategy.cs:line 51
   at Stashbox.BuildUp.Resolution.ParentContainerResolver.GetExpression(IContainerContext containerContext, TypeInformation typeInfo, ResolutionContext resolutionContext) in C:\projects\stashbox-0vuru\src\BuildUp\Resolution\ParentContainerResolver.cs:line 18
   at Stashbox.ResolutionScope.Activate(ResolutionContext resolutionContext, Type type, Object name) in C:\projects\stashbox-0vuru\src\ResolutionScope.cs:line 272
   at Stashbox.ResolutionScope.Resolve(Type typeFrom, Boolean nullResultAllowed, Object[] dependencyOverrides) in C:\projects\stashbox-0vuru\src\ResolutionScope.cs:line 94
   at Proplan.API.Common.Extensions.HangfireActivatorScope.Resolve(Type type) in C:\Users\furie\source\repos\PPBS\Proplan.API\Common\Extensions\ApplicationBuilderHangfireExtensions.cs:line 112
   --- End of inner exception stack trace ---
   at Proplan.API.Common.Extensions.HangfireActivatorScope.Resolve(Type type) in C:\Users\furie\source\repos\PPBS\Proplan.API\Common\Extensions\ApplicationBuilderHangfireExtensions.cs:line 116
   at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
   at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_0.<PerformJobWithFilters>b__0()
   at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
   at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable`1 filters)
   at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
   at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)

Here is my wiring

public static class ServiceCollectionHangfireExtensions
{
    public static IServiceCollection AddHangfire(this IServiceCollection services)
    {
        services.AddScoped<JobStorage>(_ => new SqlServerStorage(
            _.GetService<IHttpContextAccessor>().HttpContext?.RequestServices.GetRequiredService<Tenant>().ConnectionString ??
            _.GetRequiredService<Tenant>().ConnectionString,
            new SqlServerStorageOptions { PrepareSchemaIfNecessary = false }
        ));
        services.AddScoped<JobActivator>(_ => new HangfireActivator(_.GetRequiredService<IDependencyResolver>(), 
            $"RequestActivator:{_.GetService<IHttpContextAccessor>().HttpContext?.RequestServices.GetService<Tenant>()?.Name ?? _.GetService<Tenant>()?.Name}"));
        services.AddScoped<IBackgroundJobFactory>(x => new BackgroundJobFactory(x.GetRequiredService<IJobFilterProvider>()));
        services.AddScoped<IBackgroundJobStateChanger>(x => new BackgroundJobStateChanger(x.GetRequiredService<IJobFilterProvider>()));
        services.AddScoped<IBackgroundJobPerformer>(x => new BackgroundJobPerformer(x.GetRequiredService<IJobFilterProvider>(), x.GetRequiredService<JobActivator>()));
        services.AddScoped<IBackgroundJobClient>(x => new BackgroundJobClient(x.GetRequiredService<JobStorage>(), x.GetRequiredService<IBackgroundJobFactory>(), x.GetRequiredService<IBackgroundJobStateChanger>()));
        services.AddScoped<IRecurringJobManager>(x => new RecurringJobManager(x.GetRequiredService<JobStorage>(), x.GetRequiredService<IBackgroundJobFactory>()));

        return services.AddHangfire(configuration => { });
    }
}

public static class ApplicationBuilderHangfireExtensions
{
    public static IApplicationBuilder UseHangfire(this IApplicationBuilder appBuilder)
    {
        var lifetime = appBuilder.ApplicationServices.GetRequiredService<IApplicationLifetime>();
        var rootContainer = appBuilder.ApplicationServices.GetRequiredService<IStashboxContainer>();

        using (var serviceScope = appBuilder.ApplicationServices.CreateScope())
        {
            var catalogContext = serviceScope.ServiceProvider.GetRequiredService<ICatalogContext>();
        
            foreach (var tenant in catalogContext.Tenants.Where(x => x.AutomaticMigrationEnabled).AsNoTracking().ToList().Distinct(Tenant.ConnectionStringComparer))
            {
                var childContainer = InitializeChildContainer(rootContainer.CreateChildContainer(), tenant);

                CreateBackgroundJobServer(childContainer, lifetime);

                var recurringJobManager = childContainer.Resolve<IRecurringJobManager>();

                recurringJobManager.AddOrUpdate("TERRA", Job.FromExpression<ITerraService>(x => x.SyncTerrestrialDataAsync()), Cron.Weekly());
            }
        }

        return appBuilder;
    }

    private static IStashboxContainer InitializeChildContainer(IStashboxContainer container, Tenant tenant)
    {
        // Have tried both with and without this line of code, with no difference.
        container.RegisterInstance(container.Resolve<IServiceScopeFactory>().CreateScope().ServiceProvider);
        container.Register<BackgroundJobServer>(x => x.WithSingletonLifetime());
        container.Register<JobStorage>(x => x.WithFactory(y => new SqlServerStorage(tenant.ConnectionString)).WithSingletonLifetime());
        container.Register<JobActivator>(x => x.WithFactory(y => new HangfireActivator(y, tenant.Name)).WithSingletonLifetime());
        container.Register<BackgroundJobServerOptions>(x
            => x.WithFactory(y => new BackgroundJobServerOptions { ServerName = tenant.Name, WorkerCount = 1 }).WithSingletonLifetime()); // TODO: WorkerCount should probably be configurable
        container.Register<IProplanContext, ProplanContext>(x => x.WithInjectionParameters(
                new InjectionParameter { Name = "tenant", Value = tenant },
                new InjectionParameter { Name = "options", Value = new DbContextOptionsBuilder<ProplanContext>().UseSqlServer(tenant.ConnectionString).Options }
            ).WithScopedLifetime()
        );

        return container;
    }

    private static BackgroundJobServer CreateBackgroundJobServer(IDependencyResolver dependencyResolver, IApplicationLifetime lifetime)
    {
        var server = dependencyResolver.Resolve<BackgroundJobServer>();

        lifetime.ApplicationStopping.Register(() => server.SendStop());
        lifetime.ApplicationStopped.Register(() => server.Dispose());

        return server;
    }
}

public class HangfireActivator : JobActivator
{
    private readonly IDependencyResolver _dependencyResolver;
    private readonly string _scopeName;
    private int _scopeCount;

    public HangfireActivator(IDependencyResolver dependencyResolver, string scopeName = "")
    {
        _dependencyResolver = dependencyResolver;
        _scopeName = scopeName;
    }

    public override JobActivatorScope BeginScope(JobActivatorContext context)
    {
        var scopeName = $"{_scopeName}({_scopeCount++})";
        return new HangfireActivatorScope(_dependencyResolver.BeginScope(scopeName, true), context, scopeName);
    }
}

public class HangfireActivatorScope : JobActivatorScope
{
    private readonly IDependencyResolver _scope;
    private readonly JobActivatorContext _context;
    private readonly string _scopeName;

    public HangfireActivatorScope(IDependencyResolver dependencyResolver, JobActivatorContext context, string scopeName)
    {
        _scope = dependencyResolver;
        _context = context;
        _scopeName = scopeName;
    }

    public override object Resolve(Type type)
    {
        try
        {
            return _scope.Resolve(type, true);
        }
        catch (Exception ex)
        {
            throw new Exception($"[Scope: {_scopeName}][Job: {_context.BackgroundJob.Id}] failed to resolve dependency of type: {type.Name}.", ex);
        }
    }

    public override void DisposeScope() => _scope?.Dispose();
}

Issue with open generic types

The resolution of an already registered open generic type can result multiple singleton instances because the resolution process is not registering the closed variant into the container.

Generate one instance for multiple interfaces

When I use .AsImplementedTypes(), it resolves a new instance of implemented-type for each service-type. Even though, if I use .WithSingletonLifetime() !

Is that correct ?

I had expected, that one instance will be created and can be resolved with each interface.

Issue with Member Injection with Attribute but private setter

I know that i can do Memeber Injection without an Attribute and a private setter, however due to wanting to use Unknown Type Resolution which in combination with Attributeless Member Injection won't work for me, due to third party dependencies (Tries to construct an object that uses Singleton pattern) I would prefer to stick with Attributes.

I want to avoid constructor injection for objects like Loggers that have a generic parameter for the current class, especially in abstract classes because this would result in child classes having to accept two loggers in the constructor. However to use Member Injection for these, it would require that both the property and setter be public and for my senario this doesn't make sense.

Is there anyway to have the default member injection have something similar to the AutoMemberInjectionRules.PropertiesWithLimitedAccess rule for Attributeless Injection?

Edit: It appears that my issue could also be related to the fact that the members i'm trying to have injected are on a base class? Does Stashbox support this senario?

Edit: Upon further inspection, the above edit does appear to be my issue. Member Injection does not seem to check base classes for any members that might need to be injected as well. So i guess this is now a feature request? Could base classes have members being injected as well?

Circular dependency tracking doesn't work with factory resolution

I'm not too sure if this is by-design or not. Though this following code causes a stackoverflow

public interface IFoo
{
}
public class Foo : IFoo
{
    public Foo(IFoo foo)
    {

    }
}
var container = new StashboxContainer(configurator => configurator.WithCircularDependencyTracking());
container.RegisterType<IFoo, Foo>(registrator => registrator.WithFactory(() => new Foo(container.Resolve<IFoo>())));
container.Resolve<IFoo>();

The circular dependency tracking works fine if I remove the "WithFactory" bit.

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.