Asp.net mvc 2 运行时已知参数的依赖注入?
我使用IoC容器已经有一段时间了,但今天我发现代码中反复出现了一些“模式”。为了给你们一些背景知识,我现在正在开发基本上用于数据分析的web应用程序。这里有一组功能,要求用户从一开始就选择我们称之为Asp.net mvc 2 运行时已知参数的依赖注入?,asp.net-mvc-2,dependency-injection,ioc-container,Asp.net Mvc 2,Dependency Injection,Ioc Container,我使用IoC容器已经有一段时间了,但今天我发现代码中反复出现了一些“模式”。为了给你们一些背景知识,我现在正在开发基本上用于数据分析的web应用程序。这里有一组功能,要求用户从一开始就选择我们称之为QueryTypeContex。选择此查询类型后,可以执行其他步骤,但所有步骤都是在此特定的QueryTypeContex中执行的。在gui中,QueryTypeContexpick-up表示为使用其他控件打开新选项卡 当用户使用给定的QueryTypeContex时,对服务器的所有ajax调用都包括
QueryTypeContex
。选择此查询类型后,可以执行其他步骤,但所有步骤都是在此特定的QueryTypeContex
中执行的。在gui中,QueryTypeContex
pick-up表示为使用其他控件打开新选项卡
当用户使用给定的QueryTypeContex
时,对服务器的所有ajax调用都包括QueryTypeId
,它标识用户的选择,并用于在服务器上构建QueryTypeContex
,然后用于各种数据检索和操作
我发现我们的许多控制器(我们使用asp.NETMVC)都是用Ioc容器构建的,它们有一个共同点。有一个动作方法看起来有点像这样:
public class AttributeController : Controller
{
public AttributeController(IUsefulService usefulService)
{
_usefulservice = usefulService;
}
ActionResult GetAttributes(QueryTypeContex context)
{
var dataDto = _usefulService.Manipulate(context, currentUser);
return JSon(dataDto);
}
...
}
为了将QueryTypeContex
绑定到操作参数,我们使用自定义模型绑定器从数据库中提取一些信息。一旦服务获得QueryTypeContex
作为参数,它就会在实例数据访问层的方法参数中将其或其属性向下传递给其协作者。所以有一个工厂类看起来像这样
public interface IDateValueFactory
{
DateValue CurrentYear(QueryTypeContex context);
DateValue RollingMonth(int numberOfMonths, QueryTypeContex context);
DateValue RollingQuareter(int numberOfQuarters, QueryTypeContex context);
}
public class DateValueFactory : IDateValueFactory
{
public DateValueFactory(IDateValueDb dateValueDb)
{
_dateValueDb = dateValueDb;
}
public DateValue CurrentYear(QueryTypeContext context)
{
var currentYear = _dateValueDb.GetCurrentYear(context.Id);
return new DateValue(DateValueType.CurrentYear, currentYear, context);
}
public DateValue RollingMonth(int numberOfMonths, QueryTypeContex context)
{
return new DateValue(DateValueType.RollingMonth, numberOfMonths, context);
}
...
}
正如您所看到的,所有这些方法都将QueryTypeContex
作为一个参数,更重要的是它们都在其短暂的生命周期内获得了非常相同的QueryTypeContex
(一个web请求)。因此,我开始怀疑是否可以重构它,以便每当许多服务类方法需要QueryTypeContex
作为参数时,它都会通过构造函数注入,而不是通过一个函数再次传递相同的值。例如:
public interface IDateValueFactory
{
DateValue CurrentYear();
DateValue RollingMonth(int numberOfMonths);
DateValue RollingQuareter(int numberOfQuarters);
}
public class DateValueFactory : IDateValueFactory
{
public DateValueFactory(IDateValueDb dateValueDb, QueryTypeContext context)
{
_dateValueDb = dateValueDb;
_context = context;
}
public DateValue CurrentYear()
{
var currentYear = _dateValueDb.GetCurrentYear(_context.Id);
return new DateValue(DateValueType.CurrentYear, currentYear, _context);
}
public DateValue RollingMonth(int numberOfMonths)
{
return new DateValue(DateValueType.RollingMonth, numberOfMonths, _context);
}
...
}
现在真正的问题是:
这样做是个好主意还是违反了我应该遵守的一些设计原则?
为了注入使用http请求信息构建的
QueryTypeContex
实例,我考虑将QueryTypeId嵌入URI中,以便在服务器上的RoutedData中可用。然后在构建控制器之前,我可以将其拉出,构建QueryTypeContex
,为该请求创建嵌套的IoC容器,并将其注入容器中。然后,每当某个类需要QueryTypeContex
来执行其工作时,它只需将其声明为构造函数参数。任何可以作为依赖项有意义地推送到构造函数的内容,都应该这样做。与构造函数注入关联的依赖项是实现细节,而方法参数是模型API的一部分
重构通过构造函数连接的依赖项要比更改API容易得多,因此出于可维护性原因,您应该尽可能少地选择方法参数。Hmm,在这种情况下,根据给出的示例,我可能会保持上下文在方法中传递。否则,实现就是在假设如何配置它(即它的生命周期)。另外,如何通过容器、通过某种构建方法将上下文提供给构造函数?它看起来像一个抽象工厂,将上下文传递到Create()方法会更有意义吗?(需要明确的是:我不是在争论你的答案,因为我自己也在为这个问题而挣扎)。你读过指南吗?@PhoenixFF哪个指南?