Access or get Autofac Container inside a static class

前端 未结 2 1372
北荒
北荒 2021-02-09 17:36

I need to get or access to my IoC container in a static class. This is my (simplified) scenario:

I register dependencies for ASP .net Web Api in a Startup class (but als

相关标签:
2条回答
  • 2021-02-09 18:08

    I need to get or access to my IoC container in a static class. Any idea how can I get this?

    Yes, you don't! Seriously. The pattern with the static DomainEvents class originates from Udi Dahan, but even Udi has admitted that this was a bad design. Static classes that require dependencies of their own are extremely painful to work with. They make the system hard to test and maintain.

    Instead, create a IDomainEvents abstraction and inject an implementation of that abstraction into classes that require publishing events. This completely solves the your problem.

    You can define your DomainEvents class as follows:

    public interface IDomainEvents
    {
        void Raise<T>(T args) where T : IDomainEvent;
    }
    
    // NOTE: DomainEvents depends on Autofac and should therefore be placed INSIDE
    // your Composition Root.
    private class AutofacDomainEvents : IDomainEvents
    {
        private readonly IComponentContext context;
        public AutofacDomainEvents(IComponentContext context) {
            if (context == null) throw new ArgumentNullException("context");
            this.context = context;
        }
    
        public void Raise<T>(T args) where T : IDomainEvent {
            var handlers = this.context.Resolve<IEnumerable<IHandle<T>>>();
            foreach (var handler in handlers) {
                handler.Handle(args);
            }
        }
    }
    

    And you can register this class as follows:

    IContainer container = null;
    
    var builder = new ContainerBuilder();
    
    builder.RegisterType<AutofacDomainEvents>().As<IDomainEvent>()
        .InstancePerLifetimeScope();
    
    // Other registrations here
    
    container = builder.Build();
    
    0 讨论(0)
  • 2021-02-09 18:34

    You can create a static method inside your DomainEvents class to inject the container like this:

    public static class DomainEvents
    {
        public static void SetContainer(IContainer container)
        {
            Container = container;
        }
    
        ....
    }
    

    And then from your ASP.NET application, call this method to inject the container:

    DomainEvents.SetContainer(container);
    

    Please note that I am giving you a direct answer to your question. However, here are some issues that I see with this:

    • Static classes should not be used when the class requires dependencies. In such case, refactor to use a non-static class and use Constructor Injection to inject the dependencies that you need in the class.
    • Using the container outside of the Composition Root is called Service Location and is considered an anti-pattern.
    • Class libraries should not use the container or even have a Composition Root. Quoting from the Composition Root article that I referenced:

    Only applications should have Composition Roots. Libraries and frameworks shouldn't.

    0 讨论(0)
提交回复
热议问题