有方法但没有字段或属性的类实例化的速度有多快
本文关键字:实例化 速度 属性 字段 有方法 | 更新日期: 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());
}