5

一般来说,使用方法但没有字段或属性的类的实例化是否有很多开销?

我正在开发一个 ASP.NET MVC 应用程序,该应用程序大量使用构造函数注入,到目前为止,一些控制器有多达 10 个依赖项。但是由于大量的依赖项,我IMyAppServiceProvider通过 MVC 3 中的 DependencyResolver 求助于一个接口和类,它提供对所有依赖项的通用访问。

我删除了所有特定于应用程序的代码,并使用我的基本设置创建了一个Gist(但这不包括下面提到的 BaseController 设置)。

我还创建了一个接受IMyAppServiceProvider. 所有控制器都继承自这个基类。基类接受IMyAppServiceProvider对象并为所有各种服务提供受保护的变量。代码看起来像这样:

public class BaseController
{
    protected IService1 _service1;
    protected IService2 _service2;
    protected IService3 _service3;
    // ...

    public BaseController(IMyAppServiceProvider serviceProvider)
    {
        _service1 = serviceProvider.GetService<IService1>;
        _service2 = serviceProvider.GetService<IService2>;
        _service3 = serviceProvider.GetService<IService3>;
        // ...
    }
}

这使得控制器的代码“干净利落”。没有私有/受保护变量,构造函数中没有赋值,并且服务由基类受保护变量引用。 但是,每个请求都会实例化我的应用程序使用的每一个服务,无论特定控制器是否使用所有这些服务。

我的服务很简单,只包含带有一些业务逻辑和数据库交互的方法调用。它们是无状态的,没有类字段或属性。因此,实例化应该很快,但我想知道这是否是最佳实践(我知道这是一个加载术语)。

4

2 回答 2

7

每个请求都会实例化我的应用程序使用的每一个服务,无论特定控制器是否使用所有这些服务。

我相信您自己已经回答了您的问题,这不是一个好方法。此外,使用这种依赖解析(服务定位器注入)是一种不好的做法,因为控制器的 API 变得混乱。控制器客户端不知道特定控制器真正需要哪些服务,因此您最终可能会遇到意外的运行时错误,单元测试也会一团糟。

顺便说一句,还有一个建议 - 通过关键字标记所有被认为是基类的类abstract,这样您就可以避免将其用作具体类。设计和实现基类是一个具体的设计决策,所以要明确你的设计意图。

关于实例化的成本,在您的情况下不会有很大的不同,但一般来说,为了降低重对象实例化的成本,您可以:

于 2012-03-13T20:25:19.987 回答
2

我认为您在这里寻找的解决方案是使用自定义控制器工厂。这样,创建的每个控制器都具有它需要的依赖项。这是来自weblogs.asp.net的 StructureMap 的一个:

using StructureMap; 
public class StructureMapControllerFactory : DefaultControllerFactory { 

    protected override IController GetControllerInstance(Type controllerType) {
        try {
           return ObjectFactory.GetInstance(controllerType) as Controller;
        }
        catch (StructureMapException) {
            System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());
            throw;
        }
    }
}

protected void Application_Start() {
    RegisterRoutes(RouteTable.Routes);

    //Configure StructureMapConfiguration
    // TODO: config structuremap        

    //Set current Controller factory as StructureMapControllerFactory
    ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory()); 
}
于 2012-03-13T20:28:25.640 回答