简体   繁体   English

在静态类中访问或获取Autofac Container

[英]Access or get Autofac Container inside a static class

I need to get or access to my IoC container in a static class. 我需要在静态类中获取或访问我的IoC容器。 This is my (simplified) scenario: 这是我的(简化)场景:

I register dependencies for ASP .net Web Api in a Startup class (but also I do this for MVC or WCF. I have a DependecyResolver project, but for simplicity, consider the following code) 我在一个Startup类中注册ASP .net Web Api的依赖项(但我也是为MVC或WCF注册的。我有一个DependecyResolver项目,但为了简单起见,请考虑以下代码)

// Web Api project - Startup.cs
public void Configuration(IAppBuilder app)
{
    HttpConfiguration config = new HttpConfiguration();

    var builder = new ContainerBuilder();

    // ... Omited for clarity
    builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
        .AsClosedTypesOf(typeof(IHandle<>))
        .AsImplementedInterfaces();

    // ...
    IContainer container = builder.Build();
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
    // ...
}

Then, in a separate class library I have my static class (again simplified for clarity): 然后,在一个单独的类库中,我有我的静态类(为了清晰起见,再次简化):

public static class DomainEvents
{
    private static IContainer Container { get; set; }

    static DomainEvents()
    {
        //Container = I need get my Autofac container here
    }

    public static void Register<T>(Action<T> callback) where T : IDomainEvent { /* ... */ }

    public static void ClearCallbacks() { /* ... */  }

    public static void Raise<T>(T args) where T : IDomainEvent
    {
        foreach (var handler in Container.Resolve<IEnumerable<IHandle<T>>>())
        {
            handler.Handle(args);
        }
        // ...
    }
}

Any idea how can I get this? 知道我怎么能得到这个?

I need to get or access to my IoC container in a static class. 我需要在静态类中获取或访问我的IoC容器。 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. 具有静态DomainEvents类的模式源自Udi Dahan,但即使是Udi也承认这是一个糟糕的设计。 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. 相反,创建一个IDomainEvents抽象,并将该抽象的实现注入需要发布事件的类中。 This completely solves the your problem. 这完全解决了您的问题。

You can define your DomainEvents class as follows: 您可以按如下方式定义DomainEvents类:

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();

You can create a static method inside your DomainEvents class to inject the container like this: 您可以在DomainEvents类中创建一个静态方法来注入容器,如下所示:

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: 然后从ASP.NET应用程序中调用此方法来注入容器:

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 . 使用Composition Root外部的容器称为服务位置, 并被视为反模式
  • Class libraries should not use the container or even have a Composition Root. 类库不应该使用容器,甚至不能使用Composition Root。 Quoting from the Composition Root article that I referenced: 引用我引用的Composition Root文章:

Only applications should have Composition Roots. 只有应用程序应具有组合根。 Libraries and frameworks shouldn't. 图书馆和框架不应该。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM