Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to get container instance #726

Open
watoo opened this issue Jun 16, 2019 · 10 comments

Comments

Projects
None yet
3 participants
@watoo
Copy link

commented Jun 16, 2019

I'm using Asp.net MVC.

protected void Application_Start()
{
    var container = new Container();
    container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
            
    container.Register<IScrapingService, ScrapingService>(Lifestyle.Transient);

    container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
            
    container.Verify();
            
    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}

Now to get service instance in a method in another class i need container instance. How can I get the container instance over there.

I'm trying below code, it throws exception

No registration for type IScrapingService could be found. Please note that the container instance you are resolving from contains no registrations. Could it be that you accidentally created a new -and empty- container?

Container container = new SimpleInjector.Container();

IScrapingService scrapingService = container.GetInstance<IScrapingService>();

How can I get the container instance in another class?

@watoo watoo added the question label Jun 16, 2019

@dotnetjunkie

This comment has been minimized.

Copy link
Collaborator

commented Jun 16, 2019

Please note the last part of the exception message:

Could it be that you accidentally created a new -and empty- container?

This means that you are resolving from a container that has no registrations. Since you are making registrations to the container, this means that you are newing a second container instance somewhere, and are trying to resolve from that empty container.

@watoo

This comment has been minimized.

Copy link
Author

commented Jun 16, 2019

Yes, I'm creating a second instance of Container and that is empty. Now instead of initialing all the services again, how can i use my previous container object that i initialized in appliation_start.

A solution I come up with is to inject container object in MyBackGroundJobs. But how to register MyBackGroundJobs in container in application_start()

public class MyBackGroundJobs
{
    private readonly Container _container;
    public MyBackGroundJobs(Container container)
    {
        _container = container;
    }

    public void Initialize()
    {
        try
        {
            IScrapingService scrapingService = _container.GetInstance<IScrapingService>();
        }
        catch (Exception e)
        {
        }
    }
}
@dotnetjunkie

This comment has been minimized.

Copy link
Collaborator

commented Jun 16, 2019

So why are you creating a second container? You should reuse the same container instance. Why isn't that possible for you?

@watoo

This comment has been minimized.

Copy link
Author

commented Jun 16, 2019

The first container instance is in application_start() and the second container instance I need in class MyBackGroundJobs, please guide me how can i use same container instance in class MyBackGroundJobs

@dotnetjunkie

This comment has been minimized.

Copy link
Collaborator

commented Jun 16, 2019

What is blocking you from passing that container instance, which you created in application_start(), to the MyBackGroundJobs?

@watoo

This comment has been minimized.

Copy link
Author

commented Jun 17, 2019

Its design concern, if my two classes MyBackGroundJobs and SessionHandler have to use container object then its not a good idea to call them in SimpleInjectorInitializer class in application_start(). I think there should be a way through which we can get service instance whenever we need.

@dotnetjunkie

This comment has been minimized.

Copy link
Collaborator

commented Jun 17, 2019

Without seeing more code, it's impissible for me to understand your design and constraints and not possible to provide you with a solution for your problem.

@watoo

This comment has been minimized.

Copy link
Author

commented Jun 17, 2019

Please see the detailed code. Let me know if anything is unclear

ScrapingService.cs

public class ScrapingService : IScrapingService
    {
        private readonly IScrapingRepository _scrapingRepository;

        public ScrapingService(IScrapingRepository scrapingRepository)
        {
            _scrapingRepository = scrapingRepository;
        }

       public async Task Scrape(){
            //implementation
       }
}

In Global.asax.cs

protected void Application_Start()
{
       //some other stuff
       Container container = SimpleInjectorInitializer.Initialize();
       MyBackGroundJobs.Initialize(container);
}

SimpleInjectorInitializer.cs

public static class SimpleInjectorInitializer
    {
        /// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
        public static Container Initialize()
        {
            var container = new Container();
            container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
            
            InitializeContainer(container);

            container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
            
            container.Verify();
            
            DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

            return container;
        }

        private static void InitializeContainer(Container container)
        {
            container.Register<IScrapingService, ScrapingService>(Lifestyle.Transient);
            container.Register<IScrapingRepository, ScrapingRepository>(Lifestyle.Transient);
            container.Register<ApplicationDbContext>(Lifestyle.Scoped);
        }
    }

BackgroundJobs.cs

public class MyBackGroundJobs
    {
        public static void Initialize(Container container)
        {
            try
            {
                RecurringJob.AddOrUpdate( () => container.GetInstance<ScrapingService>().Scrape(), Cron.Daily); 
//getting exception: no peremeterless constructor found
            }
            catch (Exception e)
            {
            }
        }
    }
@dotnetjunkie

This comment has been minimized.

Copy link
Collaborator

commented Jun 17, 2019

Can you post a full stack trace for the exception you are getting? That should include all stack traces of the exception and inner exceptions.

@TheBigRic

This comment has been minimized.

Copy link
Collaborator

commented Jun 17, 2019

@watoo
Your question is not related to Simple Injector. As far as I can see you're trying to integrate with Hangfire. The reason your container is null is because the lambda
() => container.GetInstance<ScrapingService>().Scrape()
is serialized by Hangfire to some text and saved in the hangfire storage you chose. And when deserialized by hangfire, the container is newed by calling the constructor.... but empty! So you have to follow the integration guide from Hangfire in order to get this working.

The fact is: the way you use the container now with hangfire will never work. You'll need to implement a DependencyResolver specific for Hangfire.

I myself use hangfire and wrote an answer here on how to work with Hangfire and use scoping in a rather simple and effective way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.