有方法但没有字段或属性的类实例化的速度有多快

本文关键字:实例化 速度 属性 字段 有方法 | 更新日期: 2023-09-27 18:27:46

通常,带有方法但没有字段或属性的类的实例化会有很多开销吗?

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

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

我还创建了一个接受IMyAppServiceProvider的BaseController类。所有控制器都继承自这个基类。基类接受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>;
        // ...
    }
}

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

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

有方法但没有字段或属性的类实例化的速度有多快

每个请求都会实例化我的应用程序使用,无论特定控制器是否使用他们

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

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

关于实例化的成本,在您的情况下,这不会有太大的区别,但通常为了降低重对象实例化的成本您可以:

  • 使用原型模式来"避免以标准方式创建新对象的固有成本(例如,使用‘new’关键字),因为它对给定的应用程序来说过于昂贵"(c)维基百科
  • 对于从所有者对象生命周期开始就不需要的服务,请使用Lazy Initialization,这样这些服务将根据需要进行初始化。由于.NET Framework 4.0 yo可以使用内置的Lazy(T)类

我认为您在这里寻找的解决方案是使用自定义控制器工厂。这样,创建的每个控制器都具有所需的依赖关系。这是一个来自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()); 
}