首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >.NET依赖注入自动注册与性能

.NET依赖注入自动注册与性能
EN

Stack Overflow用户
提问于 2017-03-12 18:40:54
回答 1查看 336关注 0票数 2

我的公司在桌面应用程序中使用带有代码的统一容器作为配置。在阅读了“Auto-Registration .NET中的依赖注入”一书后,我想建议使用约定而不是配置,就像这本书所说的那样,使用组合根来组成应用程序的对象图,您应该更喜欢自动注册(以避免违反DRY并获得更易于管理的代码)。

但我也看了“普卢拉明”课程构建高性能Windows 8应用程序,作者说:

就性能而言,程序集加载是一个昂贵的过程,重要的是避免在启动路径中不必要地加载程序集。

我担心在启动时使用自动注册的性能,因为它需要使用所有程序集的反射和加载。

我喜欢了解什么是最好的方法。是否有人面临性能问题并放弃自动注册或找到中间选项?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-12 21:21:56

如果您使用DI容器(如Unity ),您基本上就有了注册依赖项的两种选择

  • 使用Auto-Registration超越配置的约定
  • 显式注册

使用Auto-Registration,您通常应用程序集扫描并反映给定程序集中的类型。这个容器中的所有类型都是Batch-Registers

另一方面,通过显式注册,您可以在代码(或XML或任何其他形式)中逐个列出所有类型。

但是,这两个选项都将导致所有包含类型的程序集在应用程序启动时被加载。

在使用DI容器时,通常很难防止这种情况发生,因为DI容器需要这些映射。典型的用途是在启动时配置容器,然后只从容器中解析。

另一方面,使用纯DI,将程序集的加载推迟到首次使用这些类型之前要容易得多。

例如,您正在使用Pure构建一个MVC web应用程序,它看起来可能有点像这样:

代码语言:javascript
复制
public static Controller CreateController(Type type)
{
    var dbContext = new CommerceContext(this.connectionString);

    if (type == typeof(HomeController))
        return 
            new HomeController(
                new ProductRepository(
                    dbContext));

    if (type == typeof(LogoutController))
        return
            new LogoutController(
                new UserRepository(
                    dbContext));

    else
        return base.CreateController(type);
}

现在假设ProductRepositoryUserRepository各自生活在不同的程序集中。现在,当第一次调用CreateController方法(启动后不久)时,这个方法将是JITted。当方法获得JITted时,将加载所有引用类型的所有程序集。在这种情况下,这意味着ProductRepository的程序集和UserRepository的程序集都将被加载。

由于HomeController很可能是在应用程序启动后不久创建的,因此尝试延迟加载ProductRepository程序集是没有什么意义的,但是对于UserRepository来说可能是有意义的,因为LogoutController可能会在应用程序生命周期的后期创建。

通过将UserRepository程序集提取到它自己的方法中,我们可以防止加载它:

代码语言:javascript
复制
public static Controller CreateController(Type type)
{
    ...
    if (type == typeof(LogoutController))
        return
            new LogoutController(
                CreateUserRepository(dbContext));
    ...
}

// Extracted to method to enable lazy assembly loading
private IUserRepository CreateUserRepository(CommerceContext context) 
{
    return new UserRepository(dbContext));
}

通过将UserRepository类的创建委托给CreateUserRepository方法,我们可以防止过早加载它的程序集。显然,这只在之前不需要该程序集中的其他类型时才有效。例如,如果在同一个程序集中定义了IUserRepository接口,这意味着当CreateController获得JITted时仍将加载程序集,因为CreateController依赖于IUserRepository

然而,这个例子有点做作,因为对于web应用程序来说,做这种延迟加载程序集通常是没有意义的,因为还有其他技术可以防止用户注意到应用程序启动时间。

这就引出了以下几点,尽管延迟在桌面应用程序中加载应用程序可能很重要,但您确实需要首先对进行度量。在许多应用程序中,这个绝对不是一个问题,。我在几个桌面应用程序上工作过,这些应用程序都使用了DI和DI容器,并在启动时对所有程序集进行了预加载,在大多数情况下性能都不是问题。

在另一个(单一)情况下,这实际上是一个问题,我们通过显示一个漂亮的启动屏幕来显示用户正在加载的应用程序,从而解决了这个问题。

尽管如此,即使在使用DI容器时,也存在延迟加载程序集的方法,但这是一个相当复杂的实践,除非存在实际的性能损失,而且无法以任何其他方式解决,否则我不会追求这种做法。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42751534

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档