在SimpleInjector how中使用构造函数注册泛型类型

本文关键字:构造函数 注册 泛型类型 SimpleInjector how | 更新日期: 2023-09-27 18:26:15

我使用Microsoft Unity作为IoC容器,并编写了如下代码:

public static void RegisterTypes(IUnityContainer container)
{
    MyContext ctx = new MyContext (); // is EntityFramework DbContext
    container.RegisterType(typeof(IEntityRepository<>),
                           typeof(EntityRepository<>), 
                           new InjectionConstructor(ctx));
    container.RegisterType(typeof(IEntityService<>), 
                           typeof(EntityService<>));
}

它对我来说毫无问题,但我想知道如何在SimpleInjector中编写它的等价物。

在SimpleInjector how中使用构造函数注册泛型类型

您的配置没有什么特别之处,@Patryk在这里为您指出了正确的文档。SimpleInjector将为您进行自动连接,因此您不必显式指定构造函数参数。

但是,您当前的设置有一些臭味,因为您的DbContext似乎是一个单例;在整个应用程序期间,您只有一个实例。在几乎所有情况下,这都是一个非常糟糕的主意。应用程序的使用寿命很长(例如Windows服务),或者同时处理多个线程(例如ASP.NET和WCF)。只有在您有一个生存时间很短的单线程应用程序(例如控制台应用程序)的情况下,您可能只有一个DbContext。您不希望将DbContext注册为singleton。

但也许它不是一个singleton,并且您实际上在每个请求中调用这个RegisterTypes一次。在这种情况下,每个请求将有一个DbContext,但这意味着每个请求都要创建一个新的容器实例,这也会很糟糕。这将对Unity和Simple Injector的性能非常不利。DI库经过特别优化,在应用程序的持续时间内只有一个容器实例。

因此,您更希望在应用程序期间有一个单独的容器实例,并让您的DbContext通常使用Scoped生活方式注册。

在Simple Injector中,有许多范围内的生活方式,每种生活方式都特定于所选的技术。假设您使用MVC,您的注册可能如下所示:

public static void RegisterTypes(Container container)
{
    container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
    container.Register<MyContex>(Lifestyle.Scoped);
    container.Register(typeof(IEntityRepository<>), typeof(EntityRepository<>));
    container.Register(typeof(IEntityService<>), typeof(EntityService<>));
}

请注意EntityRepository<T>的注册。如果EntityRepository<T>的构造函数参数为MyContext,并且MyContext已在容器中注册,则Simple Injector将能够在其构造函数中为您注入此依赖项。这个过程被称为自动连接,通常应该让容器为您完成这项工作,因为这会使DI配置更易于维护。