【问题标题】:Passing a service to a controller in .NET MVC framework将服务传递给 .NET MVC 框架中的控制器
【发布时间】:2017-07-10 01:21:49
【问题描述】:

我有一个 .NET MVC 应用程序,我需要将我的服务传递给控制器​​。控制器应该使用该服务,检索所有仪器并将它们传递给视图。这样做的正确方法是什么?

这里是我的控制器:

   public class MyController: Controller
    {
        private MyService db;

        public IActionResult Index()
        {
            var res = db.Instrument;
            return View(res);
        }
    }

我想使用db,但它需要以某种方式传递。在MyService 服务下方:

   public class MyService : IMyService
    {
        private readonly IServiceProvider serviceProvider;

        public MyService(IServiceProvider serviceProvider)
        {
            this.serviceProvider = serviceProvider;
            Instrument = null;
        }

        public Instrument Instrument { get; private set; }
    }

【问题讨论】:

  • -1 的原因?
  • 对不起,我不明白你的问题。首先,您在控制器中的代码,您使用 db 变量而不启动。这根本没有意义。我猜你想自动创建实例。是吗?

标签: c# asp.net .net asp.net-mvc-4 model-view-controller


【解决方案1】:

首先,我将设置控制器,使其不必创建它所依赖的对象来完成其工作(请参阅Inversion of Control)。

因此,控制器可能如下所示:

public class MyController: Controller
{
    private readonly IMyService myService;

    public MyController(IMyService myService)
    {
        this.myService = myService;
    }

    ...
}

请注意,服务是通过控制器构造函数传递给控制器​​的,并且控制器依赖于服务接口而不是实际的服务类型。控制器不需要关心服务从哪里来或如何实现的,只要它符合指定的接口即可。

所以现在,您可以使用该服务来获取您的信息:

public class MyController: Controller
{
    private readonly IMyService myService;

    public MyController(IMyService myService)
    {
        this.myService = myService;
    }

    public ViewResult Index()
    {
        var instruments = this.myService.GetInstruments();
        return View(instruments);
    }
}

请注意,我已更改您的服务实现以检索您在描述中指定的所有仪器,您希望检索所有仪器。

另外,请注意,为了简单起见,我刚刚将服务返回的类型直接传递给视图。但是,我通常建议使用视图模型,但我会将其作为练习留给读者。

至于服务本身,您可能有:

public class MyService : IMyService
{
    private readonly IDataProvider dataProvider;

    public MyService(IDataProvider dataProvider)
    {
        this.dataProvider = dataProvider;
    }

    public IEnumerable<Instrument> GetInstruments()
    {
        return dataProvider.GetInstruments();
    }
}

我不确定IServiceProvider 是什么,所以我将其重命名为IDataProvider。您可以在此处获取所需的任何数据以获取服务中的数据。例如,您可以改为将IDbContext(如果使用实体框架)传入构造函数并使用它来获取数据。

我还必须指出,如果您的应用程序非常简单,业务用例场景非常简单,那么您甚至可能不需要这个服务层,而是将数据提供者直接传递到构造函数中。同样,我将把这个作为练习留给读者。

最后,要将IMyService 的实现传递给构造函数并将IDataProvider 的实现传递给MyService,您可以使用dependency injection 框架。

当 MVC 实例化一个控制器时,它会查看依赖注入框架来找出如何创建所需的依赖项。在此示例中,当调用 Index() 操作时,MVC 将尝试创建 MyService 的实例。它将让依赖注入框架创建一个实现IMyService 的实例。依赖注入框架将查看其设置并确定它需要创建MyService 的实例,但此实现本身需要IDataProvider 的实例。因此依赖注入框架将再次查看其设置并确定它需要创建DataProvider 的实例。它将DataProvider的实例传递给MyService,然后将MyService的实例传递给MyController,然后MVC最终将调用Index()操作方法,然后操作方法将可以访问该服务.

一个常见的依赖注入框架的例子是 Ninject。您可以设置规则来告诉框架对于给定接口,这是所需的实例类型。例如:

this.Bind<IMyService>().To<MyService>();
this.Bind<IDataProvider>().To<DataProvider();

最后,(假设您使用的是 razor 视图)视图顶部的声明可能类似于:

@model IEnumerable<Instrument>

// You are now able to use @Model. in the view to provide you the information you require.

我希望这会有所帮助,但这只是对您的情况的一个非常简短的介绍。因此,我建议阅读 inversion of controldependency injectionNinject 作为潜在的依赖注入框架,尽管还有其他各种框架。

【讨论】:

    猜你喜欢
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 2012-12-31
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多