在asp.net-mvc中有没有更好的方法来实现IOC?

在asp.net-mvc中有没有更好的方法来实现IOC?,asp.net-mvc,interface,inversion-of-control,linfu,Asp.net Mvc,Interface,Inversion Of Control,Linfu,我有一个asp.net-mvc网站,我正在使用LinFu做IOC。我遇到了一个问题,许多操作都有一个依赖项,我想将其注入控制器,但我只想在调用依赖它的操作时初始化该依赖项 因此,在我的控制器中,我的控制器中有以下代码: public PersonController { private IPeopleImporter _peopleImporter; public override void Initialize(LinFu.IoC.Interfaces.ISer

我有一个asp.net-mvc网站,我正在使用LinFu做IOC。我遇到了一个问题,许多操作都有一个依赖项,我想将其注入控制器,但我只想在调用依赖它的操作时初始化该依赖项

因此,在我的控制器中,我的控制器中有以下代码:

   public PersonController
   {

    private IPeopleImporter _peopleImporter;

    public override void Initialize(LinFu.IoC.Interfaces.IServiceContainer source)
    {
        _peopleImporter= source.GetService<IPeopleImporter>();
        base.Initialize(source);
    }

    public JsonResult GetDetails(int id)
    {
        var p = _peopleImporter.Get(id);
        var personDetails = new {p.Id, p.FirstName, p.LastName, StandardId = p.StandardIdLogin, p.PersonNumber};
        return Json(personDetails);
    }
   }

这似乎是常见的模式/问题。是否有推荐的解决方案。同时,避免性能受到影响的另一种方法是简化控制器内部的concete实现,避免IOC?

我通常通过将依赖项作为参数注入到我的操作中来解决这个问题。普通的或廉价的依赖项可以在类级别注入,而不寻常的或昂贵的依赖项可以作为参数注入

以下是企业库Unity的一些示例代码,但您可以对其进行调整:

public class UnityActionInvoker : ControllerActionInvoker
{
    readonly IUnityContainer container;

    public UnityActionInvoker(IUnityContainer container)
    {
        this.container = container;
    }

    protected override object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
    {
        Type parameterType = parameterDescriptor.ParameterType;

        if (parameterType != typeof(string) && !parameterType.IsValueType && container.IsRegistered(parameterType))
        {
            return container.Resolve(parameterType).AssertNotNull();
        }

        return base.GetParameterValue(controllerContext, parameterDescriptor);
    }
}
您可以通过在控制器的构造函数或所有控制器的公共基类中设置Controller.ActionInvoker来钩住此ControllerActionInvoker

以下是控制器的外观:

   public PersonController
   {
    public JsonResult GetDetails(int id, IPeopleImporter _peopleImporter /*injected*/)
    {
        ...
    }
   }

我通常通过将依赖项作为参数注入到我的操作中来解决这个问题。普通的或廉价的依赖项可以在类级别注入,而不寻常的或昂贵的依赖项可以作为参数注入

以下是企业库Unity的一些示例代码,但您可以对其进行调整:

public class UnityActionInvoker : ControllerActionInvoker
{
    readonly IUnityContainer container;

    public UnityActionInvoker(IUnityContainer container)
    {
        this.container = container;
    }

    protected override object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
    {
        Type parameterType = parameterDescriptor.ParameterType;

        if (parameterType != typeof(string) && !parameterType.IsValueType && container.IsRegistered(parameterType))
        {
            return container.Resolve(parameterType).AssertNotNull();
        }

        return base.GetParameterValue(controllerContext, parameterDescriptor);
    }
}
您可以通过在控制器的构造函数或所有控制器的公共基类中设置Controller.ActionInvoker来钩住此ControllerActionInvoker

以下是控制器的外观:

   public PersonController
   {
    public JsonResult GetDetails(int id, IPeopleImporter _peopleImporter /*injected*/)
    {
        ...
    }
   }

第一步是将此操作放入一个单独的控制器中。因此,您不必为此控制器中的其他操作支付初始化费用

然后使用真正的IoC模式,而不是您当前使用的被视为反模式的服务定位器。在IoC中,控制器不应该知道所使用的特定DI框架的任何信息。在IoC中,控制器接收所有依赖项作为构造函数参数

public PersonsController: Controller
{
    private readonly IPeopleImporter _peopleImporter;
    public PersonsController(IPeopleImporter peopleImporter)
    {
        _peopleImporter = peopleImporter;
    }

    public ActionResult GetDetails(int id)
    {
        var p = _peopleImporter.Get(id);
        var personDetails = new { p.Id, p.FirstName, p.LastName, StandardId = p.StandardIdLogin, p.PersonNumber };
        return Json(personDetails, JsonRequestBehavior.AllowGet);
    }
}

第一步是将此操作放入一个单独的控制器中。因此,您不必为此控制器中的其他操作支付初始化费用

然后使用真正的IoC模式,而不是您当前使用的被视为反模式的服务定位器。在IoC中,控制器不应该知道所使用的特定DI框架的任何信息。在IoC中,控制器接收所有依赖项作为构造函数参数

public PersonsController: Controller
{
    private readonly IPeopleImporter _peopleImporter;
    public PersonsController(IPeopleImporter peopleImporter)
    {
        _peopleImporter = peopleImporter;
    }

    public ActionResult GetDetails(int id)
    {
        var p = _peopleImporter.Get(id);
        var personDetails = new { p.Id, p.FirstName, p.LastName, StandardId = p.StandardIdLogin, p.PersonNumber };
        return Json(personDetails, JsonRequestBehavior.AllowGet);
    }
}

您可以在任务中使用下一个技巧。 您可以注入的不是IPeoplimPorter的实例,而是此类型的工厂:

private readonly Func<IPeopleImporter> _peopleImporterFactory;
例如:

 public PersonController
{


}

您可以在任务中使用下一个技巧。 您可以注入的不是IPeoplimPorter的实例,而是此类型的工厂:

private readonly Func<IPeopleImporter> _peopleImporterFactory;
例如:

 public PersonController
{


}

我不知道LinFu的情况,但许多其他IOC框架提供了工厂注入,可以在需要时用于实例化实例。您展示的不是IOC。你一定把这里的术语弄混了。在IoC中,控制器将依赖项作为构造函数参数。在您的示例中,您将控制器绑定到DI框架LinFu(在您的示例中),并且在您查询DI框架以检索依赖项的初始化方法中使用服务定位器模式。这被认为是一种反模式。我不知道LinFu,但许多其他IOC框架提供工厂注入,可以在需要时用于实例化实例。您展示的不是IOC。你一定把这里的术语弄混了。在IoC中,控制器将依赖项作为构造函数参数。在您的示例中,您将控制器绑定到DI框架LinFu(在您的示例中),并且在您查询DI框架以检索依赖项的初始化方法中使用服务定位器模式。这被认为是一种反模式。在IoC中,可以通过构造函数以外的其他方式注入依赖项。当然构造函数是最常见的,但不是唯一可能的mechanism@RuneFS是的,没错。您可以对非必需的依赖项使用属性注入。@Darin-我同意您的观点。考虑到Linfu似乎不支持适当的IOC,控制器不需要对IOC容器的引用,此时希望从Linfu迁移出去。在IOC中,您可以通过构造函数以外的其他方式注入依赖项。当然构造函数是最常见的,但不是唯一可能的mechanism@RuneFS是的,没错。您可以对非必需的依赖项使用属性注入。@Darin-我同意您的观点。考虑到Linfu似乎不支持适当的IOC,控制器不需要对IOC容器的引用,因此现在希望迁移到Linfu之外。